@ -2510,6 +2510,66 @@ static inline uint32_t StreamTcpResetGetMaxAck(TcpStream *stream, uint32_t seq)
SCReturnUInt ( ack ) ;
SCReturnUInt ( ack ) ;
}
}
/** \internal
* \ brief check if a ACK packet is outdated so processing can be fast tracked
*
* Consider a packet outdated ack if :
* - state is > = ESTABLISHED
* - ACK < last_ACK
* - SACK acks nothing new
* - packet has no data
* - SEQ = = next_SEQ
* - flags has ACK set but don ' t contain SYN / FIN / RST
*
* \ todo the most likely explanation for this packet is that we already
* accepted a " newer " ACK . We will not consider an outdated timestamp
* option an issue for this packet , but we should probably still
* check if the ts isn ' t too far off .
*/
static bool StreamTcpPacketIsOutdatedAck ( TcpSession * ssn , Packet * p )
{
if ( ssn - > state < TCP_ESTABLISHED )
return false ;
if ( p - > payload_len ! = 0 )
return false ;
if ( ( p - > tcph - > th_flags & ( TH_ACK | TH_SYN | TH_FIN | TH_RST ) ) ! = TH_ACK )
return false ;
/* lets see if this is a packet that is entirely eclipsed by earlier ACKs */
if ( PKT_IS_TOSERVER ( p ) ) {
if ( SEQ_EQ ( TCP_GET_SEQ ( p ) , ssn - > client . next_seq ) & &
SEQ_LT ( TCP_GET_ACK ( p ) , ssn - > server . last_ack ) ) {
if ( ! TCP_HAS_SACK ( p ) ) {
SCLogDebug ( " outdated ACK (no SACK, SEQ %u vs next_seq %u) " , TCP_GET_SEQ ( p ) ,
ssn - > client . next_seq ) ;
return true ;
}
if ( StreamTcpSackPacketIsOutdated ( & ssn - > server , p ) ) {
SCLogDebug ( " outdated ACK (have SACK, SEQ %u vs next_seq %u) " , TCP_GET_SEQ ( p ) ,
ssn - > client . next_seq ) ;
return true ;
}
}
} else {
if ( SEQ_EQ ( TCP_GET_SEQ ( p ) , ssn - > server . next_seq ) & &
SEQ_LT ( TCP_GET_ACK ( p ) , ssn - > client . last_ack ) ) {
if ( ! TCP_HAS_SACK ( p ) ) {
SCLogDebug ( " outdated ACK (no SACK, SEQ %u vs next_seq %u) " , TCP_GET_SEQ ( p ) ,
ssn - > client . next_seq ) ;
return true ;
}
if ( StreamTcpSackPacketIsOutdated ( & ssn - > client , p ) ) {
SCLogDebug ( " outdated ACK (have SACK, SEQ %u vs next_seq %u) " , TCP_GET_SEQ ( p ) ,
ssn - > client . next_seq ) ;
return true ;
}
}
}
return false ;
}
/**
/**
* \ brief Function to handle the TCP_ESTABLISHED state . The function handles
* \ brief Function to handle the TCP_ESTABLISHED state . The function handles
* ACK , FIN , RST packets and correspondingly changes the connection
* ACK , FIN , RST packets and correspondingly changes the connection
@ -4893,10 +4953,14 @@ int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
/* if packet is not a valid window update, check if it is perhaps
/* if packet is not a valid window update, check if it is perhaps
* a bad window update that we should ignore ( and alert on ) */
* a bad window update that we should ignore ( and alert on ) */
if ( StreamTcpPacketIsFinShutdownAck ( ssn , p ) = = 0 )
if ( StreamTcpPacketIsFinShutdownAck ( ssn , p ) = = 0 ) {
if ( StreamTcpPacketIsWindowUpdate ( ssn , p ) = = 0 )
if ( StreamTcpPacketIsWindowUpdate ( ssn , p ) = = 0 ) {
if ( StreamTcpPacketIsBadWindowUpdate ( ssn , p ) )
if ( StreamTcpPacketIsBadWindowUpdate ( ssn , p ) )
goto skip ;
goto skip ;
if ( StreamTcpPacketIsOutdatedAck ( ssn , p ) )
goto skip ;
}
}
/* handle the per 'state' logic */
/* handle the per 'state' logic */
if ( StreamTcpStateDispatch ( tv , p , stt , ssn , & stt - > pseudo_queue , ssn - > state ) < 0 )
if ( StreamTcpStateDispatch ( tv , p , stt , ssn , & stt - > pseudo_queue , ssn - > state ) < 0 )