diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 2e69204e14..0f69138310 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -3310,10 +3310,10 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *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)); - + int retransmission = 0; if (StreamTcpPacketIsRetransmission(&ssn->client, p)) { SCLogDebug("ssn %p: packet is retransmission", ssn); - SCReturnInt(-1); + retransmission = 1; } if (TCP_GET_SEQ(p) != ssn->client.next_seq) { @@ -3330,10 +3330,12 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, return -1; } - StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT); - SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn); + if (!retransmission) { + StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT); + SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn); - ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + } StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p)); @@ -3354,10 +3356,10 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ " "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); - + int retransmission = 0; if (StreamTcpPacketIsRetransmission(&ssn->server, p)) { SCLogDebug("ssn %p: packet is retransmission", ssn); - SCReturnInt(-1); + retransmission = 1; } if (TCP_GET_SEQ(p) != ssn->server.next_seq) { @@ -3374,10 +3376,12 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, return -1; } - StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT); - SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn); + if (!retransmission) { + StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT); + SCLogDebug("ssn %p: state changed to TCP_TIME_WAIT", ssn); - ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + } StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p)); @@ -3592,9 +3596,10 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); - if (StreamTcpPacketIsRetransmission(&ssn->client, p)) { + int retransmission = 0; + if (StreamTcpPacketIsRetransmission(&ssn->client, p) == 1) { SCLogDebug("ssn %p: packet is retransmission", ssn); - SCReturnInt(-1); + retransmission = 1; } if (p->payload_len > 0 && (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), ssn->client.last_ack))) { @@ -3617,7 +3622,9 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, SCReturnInt(-1); } - ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; + if (!retransmission) { + ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; + } StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p)); @@ -3642,10 +3649,10 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ " "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); - + int retransmission = 0; if (StreamTcpPacketIsRetransmission(&ssn->server, p)) { SCLogDebug("ssn %p: packet is retransmission", ssn); - SCReturnInt(-1); + retransmission = 1; } if (p->payload_len > 0 && (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), ssn->server.last_ack))) { @@ -3668,7 +3675,9 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, SCReturnInt(-1); } - ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + if (!retransmission) { + ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + } StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p)); @@ -3774,9 +3783,10 @@ static int StreamTcpPacketStateLastAck(ThreadVars *tv, Packet *p, "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); + int retransmission = 0; if (StreamTcpPacketIsRetransmission(&ssn->client, p)) { SCLogDebug("ssn %p: packet is retransmission", ssn); - SCReturnInt(-1); + retransmission = 1; } if (TCP_GET_SEQ(p) != ssn->client.next_seq && TCP_GET_SEQ(p) != ssn->client.next_seq + 1) { @@ -3793,10 +3803,12 @@ static int StreamTcpPacketStateLastAck(ThreadVars *tv, Packet *p, SCReturnInt(-1); } - StreamTcpPacketSetState(p, ssn, TCP_CLOSED); - SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn); + if (!retransmission) { + StreamTcpPacketSetState(p, ssn, TCP_CLOSED); + SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn); - ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; + ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; + } StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p)); @@ -3898,13 +3910,12 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *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)); - + int retransmission = 0; if (StreamTcpPacketIsRetransmission(&ssn->client, p)) { SCLogDebug("ssn %p: packet is retransmission", ssn); - SCReturnInt(-1); - } + retransmission = 1; - if (TCP_GET_SEQ(p) != ssn->client.next_seq && TCP_GET_SEQ(p) != ssn->client.next_seq+1) { + } else if (TCP_GET_SEQ(p) != ssn->client.next_seq && TCP_GET_SEQ(p) != ssn->client.next_seq+1) { SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" " != %" PRIu32 " from stream", ssn, TCP_GET_SEQ(p), ssn->client.next_seq); @@ -3918,10 +3929,12 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, SCReturnInt(-1); } - StreamTcpPacketSetState(p, ssn, TCP_CLOSED); - SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn); + if (!retransmission) { + StreamTcpPacketSetState(p, ssn, TCP_CLOSED); + SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn); - ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; + ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; + } StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p)); @@ -3945,13 +3958,11 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ " "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); - + int retransmission = 0; if (StreamTcpPacketIsRetransmission(&ssn->server, p)) { SCLogDebug("ssn %p: packet is retransmission", ssn); - SCReturnInt(-1); - } - - if (TCP_GET_SEQ(p) != ssn->server.next_seq && TCP_GET_SEQ(p) != ssn->server.next_seq+1) { + retransmission = 1; + } else if (TCP_GET_SEQ(p) != ssn->server.next_seq && TCP_GET_SEQ(p) != ssn->server.next_seq+1) { if (p->payload_len > 0 && TCP_GET_SEQ(p) == ssn->server.last_ack) { SCLogDebug("ssn %p: -> retransmission", ssn); SCReturnInt(0); @@ -3970,10 +3981,12 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, SCReturnInt(-1); } - StreamTcpPacketSetState(p, ssn, TCP_CLOSED); - SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn); + if (!retransmission) { + StreamTcpPacketSetState(p, ssn, TCP_CLOSED); + SCLogDebug("ssn %p: state changed to TCP_CLOSED", ssn); - ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + } StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p));