support for validating the ACK before updating the last_ack field and also update next_seq if we missed the last packet

remotes/origin/master-1.1.x
Gurvinder Singh 15 years ago committed by Victor Julien
parent acc38c9ebf
commit 2beb7af7f8

@ -582,6 +582,29 @@ void StreamTcpSetOSPolicy(TcpStream *stream, Packet *p)
}
/**
* \brief Function to test the received ACK values against the stream window
* and previous ack value. ACK values should be higher than previous
* ACK value and less than the next_win value.
*
* \param stream TcpStream of which last_ack needs to be tested
* \param p Packet which is used to test the last_ack
*
* \retval on valid ACK it return TRUE and on invalid ACK, it returns FALSE
*/
static inline uint8_t StreamTcpValidateAck(TcpStream *stream, Packet *p)
{
uint8_t ret = FALSE;
if (SEQ_GT(TCP_GET_ACK(p), stream->last_ack) &&
(SEQ_LEQ(TCP_GET_ACK(p) + p->payload_len, stream->next_win)))
{
ret = TRUE;
}
return ret;
}
/**
* \brief Function to handle the TCP_CLOSED or NONE state. The function handles
* packets while the session state is None which means a newly
@ -1230,6 +1253,9 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
if ((SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq))) {
SCLogDebug("4WHS normal pkt");
/* we need to make sure that both sequence and the ack are
of sane values */
if ((StreamTcpValidateAck(&ssn->client, p) == TRUE))
ssn->client.last_ack = TCP_GET_ACK(p);
ssn->server.next_seq += p->payload_len;
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
@ -1284,7 +1310,11 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
/* process the packet normal, No Async streams :) */
/* 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->client.next_seq += p->payload_len;
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
@ -1520,8 +1550,14 @@ static int HandleEstablishedPacketToServer(ThreadVars *tv, TcpSession *ssn, Pack
SCLogDebug("ssn %p: ssn->server.window %"PRIu32"", ssn,
ssn->server.window);
if (SEQ_GT(TCP_GET_ACK(p), ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the server packet
and client has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
if (SEQ_GT((ssn->server.last_ack + ssn->server.window),
ssn->server.next_win))
@ -1608,8 +1644,14 @@ static int HandleEstablishedPacketToClient(ThreadVars *tv, TcpSession *ssn, Pack
SCLogDebug("ssn %p: ssn->client.window %"PRIu32"", ssn,
ssn->client.window);
if (SEQ_GT(TCP_GET_ACK(p), ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client packet
and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
if (SEQ_GT((ssn->client.last_ack + ssn->client.window),
ssn->client.next_win))
@ -1751,8 +1793,10 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p,
ssn->server.next_seq);
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
@ -1772,8 +1816,10 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p,
ssn->server.next_seq);
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, p, pq);
@ -1824,14 +1870,20 @@ static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *stt,
SCLogDebug("ssn %p: state changed to TCP_CLOSE_WAIT", ssn);
if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq))
ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1;
ssn->server.next_seq = TCP_GET_ACK(p);
SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn,
ssn->server.next_seq);
ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len;
SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "", ssn,
ssn->client.next_seq);
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client packet
and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq);
@ -1855,14 +1907,20 @@ static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *stt,
SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT1", ssn);
if (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq))
ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1;
ssn->client.next_seq = TCP_GET_ACK(p);
ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len;
SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn,
ssn->server.next_seq);
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client packet
and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p, pq);
@ -1915,8 +1973,14 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
@ -1945,8 +2009,14 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT2", ssn);
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, p, pq);
@ -1995,8 +2065,14 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
@ -2030,8 +2106,14 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, p, pq);
@ -2117,8 +2199,14 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
@ -2148,8 +2236,14 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, p, pq);
@ -2210,8 +2304,14 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
@ -2238,8 +2338,14 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, p, pq);
@ -2299,8 +2405,14 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p,
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
@ -2323,8 +2435,14 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn);
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, p, pq);
@ -2396,8 +2514,14 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: state changed to TCP_LAST_ACK", ssn);
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, p, pq);
@ -2423,8 +2547,14 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: state changed to TCP_LAST_ACK", ssn);
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
@ -2458,8 +2588,14 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
}
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
if (SEQ_EQ(TCP_GET_SEQ(p),ssn->server.next_seq))
ssn->server.next_seq += p->payload_len;
@ -2485,8 +2621,14 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
}
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
if (SEQ_EQ(TCP_GET_SEQ(p),ssn->client.next_seq))
ssn->client.next_seq += p->payload_len;
@ -2548,8 +2690,14 @@ static int StreamTcpPakcetStateLastAck(ThreadVars *tv, Packet *p,
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
@ -2610,8 +2758,14 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p,
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->server, p) == TRUE) {
ssn->server.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->server.next_seq, TCP_GET_ACK(p)))
ssn->server.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, p, pq);
@ -2636,8 +2790,14 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn);
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
/* Check if the ACK value is sane and inside the window limit */
if (StreamTcpValidateAck(&ssn->client, p) == TRUE) {
ssn->client.last_ack = TCP_GET_ACK(p);
/* Update the next_seq, in case if we have missed the client
packet and server has already received and acked it */
if (SEQ_LT(ssn->client.next_seq, TCP_GET_ACK(p)))
ssn->client.next_seq = TCP_GET_ACK(p);
}
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, p, pq);
@ -7304,6 +7464,242 @@ end:
SCFree(p);
return ret;
}
/**
* \test Test the validation of the ACK number before setting up the
* stream.last_ack.
*
* \retval On success it returns 1 and on failure 0.
*/
static int StreamTcpTest38 (void) {
int ret = 0;
Flow f;
ThreadVars tv;
StreamTcpThread stt;
uint8_t payload[4];
TCPHdr tcph;
TcpReassemblyThreadCtx ra_ctx;
StreamMsgQueue stream_q;
PacketQueue pq;
memset(&stream_q, 0, sizeof(StreamMsgQueue));
memset(&ra_ctx, 0, sizeof(TcpReassemblyThreadCtx));
memset (&f, 0, sizeof(Flow));
memset(&tv, 0, sizeof (ThreadVars));
memset(&stt, 0, sizeof (StreamTcpThread));
memset(&tcph, 0, sizeof (TCPHdr));
memset(&pq,0,sizeof(PacketQueue));
Packet *p = SCMalloc(SIZE_OF_PACKET);
if (p == NULL)
return 0;
memset(p, 0, SIZE_OF_PACKET);
p->pkt = (uint8_t *)(p + 1);
p->flow = &f;
tcph.th_win = htons(5480);
tcph.th_flags = TH_SYN;
p->tcph = &tcph;
p->flowflags = FLOW_PKT_TOSERVER;
ra_ctx.stream_q = &stream_q;
stt.ra_ctx = &ra_ctx;
StreamTcpInitConfig(TRUE);
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
p->tcph->th_ack = htonl(1);
p->tcph->th_flags = TH_SYN | TH_ACK;
p->flowflags = FLOW_PKT_TOCLIENT;
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
p->tcph->th_ack = htonl(1);
p->tcph->th_seq = htonl(1);
p->tcph->th_flags = TH_ACK;
p->flowflags = FLOW_PKT_TOSERVER;
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
p->tcph->th_ack = htonl(29847);
p->tcph->th_seq = htonl(2);
p->tcph->th_flags = TH_PUSH | TH_ACK;
p->flowflags = FLOW_PKT_TOSERVER;
StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
p->payload = payload;
p->payload_len = 3;
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
/* last_ack value should be 1 as the previous sent ACK value is out of
window */
if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 1) {
printf("the server.last_ack should be 1, but it is %"PRIu32"\n",
((TcpSession *)(p->flow->protoctx))->server.last_ack);
goto end;
}
p->tcph->th_ack = htonl(2984);
p->tcph->th_seq = htonl(5);
p->tcph->th_flags = TH_PUSH | TH_ACK;
p->flowflags = FLOW_PKT_TOSERVER;
StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
p->payload = payload;
p->payload_len = 3;
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
/* last_ack value should be 2984 as the previous sent ACK value is inside
window */
if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 2984) {
printf("the server.last_ack should be 2984, but it is %"PRIu32"\n",
((TcpSession *)(p->flow->protoctx))->server.last_ack);
goto end;
}
ret = 1;
end:
StreamTcpSessionClear(p->flow->protoctx);
StreamTcpFreeConfig(TRUE);
return ret;
}
/**
* \test Test the validation of the ACK number before setting up the
* stream.last_ack and update the next_seq after loosing the .
*
* \retval On success it returns 1 and on failure 0.
*/
static int StreamTcpTest39 (void) {
Flow f;
ThreadVars tv;
StreamTcpThread stt;
uint8_t payload[4];
TCPHdr tcph;
TcpReassemblyThreadCtx ra_ctx;
StreamMsgQueue stream_q;
PacketQueue pq;
memset(&stream_q, 0, sizeof(StreamMsgQueue));
memset(&ra_ctx, 0, sizeof(TcpReassemblyThreadCtx));
memset (&f, 0, sizeof(Flow));
memset(&tv, 0, sizeof (ThreadVars));
memset(&stt, 0, sizeof (StreamTcpThread));
memset(&tcph, 0, sizeof (TCPHdr));
memset(&pq,0,sizeof(PacketQueue));
Packet *p = SCMalloc(SIZE_OF_PACKET);
if (p == NULL)
return 0;
memset(p, 0, SIZE_OF_PACKET);
p->pkt = (uint8_t *)(p + 1);
p->flow = &f;
tcph.th_win = htons(5480);
tcph.th_flags = TH_SYN;
p->tcph = &tcph;
p->flowflags = FLOW_PKT_TOSERVER;
int ret = 0;
ra_ctx.stream_q = &stream_q;
stt.ra_ctx = &ra_ctx;
StreamTcpInitConfig(TRUE);
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
p->tcph->th_ack = htonl(1);
p->tcph->th_flags = TH_SYN | TH_ACK;
p->flowflags = FLOW_PKT_TOCLIENT;
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
p->tcph->th_ack = htonl(1);
p->tcph->th_seq = htonl(1);
p->tcph->th_flags = TH_ACK;
p->flowflags = FLOW_PKT_TOSERVER;
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
p->tcph->th_ack = htonl(2984);
p->tcph->th_seq = htonl(2);
p->tcph->th_flags = TH_PUSH | TH_ACK;
p->flowflags = FLOW_PKT_TOSERVER;
StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
p->payload = payload;
p->payload_len = 3;
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
/* last_ack value should be 2984 as the previous sent ACK value is inside
window */
if (((TcpSession *)(p->flow->protoctx))->server.last_ack != 2984) {
printf("the server.last_ack should be 2984, but it is %"PRIu32"\n",
((TcpSession *)(p->flow->protoctx))->server.last_ack);
goto end;
}
p->tcph->th_seq = htonl(2984);
p->tcph->th_ack = htonl(5);
p->tcph->th_flags = TH_PUSH | TH_ACK;
p->flowflags = FLOW_PKT_TOCLIENT;
StreamTcpCreateTestPacket(payload, 0x41, 3, 4); /*AAA*/
p->payload = payload;
p->payload_len = 3;
if (StreamTcpPacket(&tv, p, &stt, &pq) == -1) {
printf("failed in processing packet in StreamTcpPacket\n");
goto end;
}
/* next_seq value should be 2987 as the previous sent ACK value is inside
window */
if (((TcpSession *)(p->flow->protoctx))->server.next_seq != 2987) {
printf("the server.next_seq should be 2987, but it is %"PRIu32"\n",
((TcpSession *)(p->flow->protoctx))->server.next_seq);
goto end;
}
ret = 1;
end:
StreamTcpSessionClear(p->flow->protoctx);
StreamTcpFreeConfig(TRUE);
return ret;
}
#endif /* UNITTESTS */
void StreamTcpRegisterTests (void) {
@ -7355,6 +7751,7 @@ void StreamTcpRegisterTests (void) {
UtRegisterTest("StreamTcpTest27 -- test ecn/cwr sessions",
StreamTcpTest27, 1);
UtRegisterTest("StreamTcpTest28 -- Memcap Test", StreamTcpTest28, 1);
#if 0 /* VJ 2010/09/01 disabled since they blow up on Fedora and Fedora is
* right about blowing up. The checksum functions are not used properly
* in the tests. */
@ -7369,6 +7766,9 @@ void StreamTcpRegisterTests (void) {
#endif
UtRegisterTest("StreamTcpTest37 -- Out of order FIN Test", StreamTcpTest37, 1);
UtRegisterTest("StreamTcpTest38 -- validate ACK", StreamTcpTest38, 1);
UtRegisterTest("StreamTcpTest39 -- update next_seq", StreamTcpTest39, 1);
/* set up the reassembly tests as well */
StreamTcpReassembleRegisterTests();
#endif /* UNITTESTS */

Loading…
Cancel
Save