@ -40,9 +40,6 @@
# include "app-layer-dnp3.h"
# include "app-layer-dnp3-objects.h"
/* Default number of unreplied requests to be considered a flood. */
# define DNP3_DEFAULT_REQ_FLOOD_COUNT 500
# define DNP3_DEFAULT_PORT "20000"
/* Expected values for the start bytes. */
@ -93,6 +90,14 @@ enum {
/* Extract the range code from the object qualifier. */
# define DNP3_OBJ_RANGE(x) (x & 0xf)
/* Default number of unreplied requests to be considered a flood.
*
* DNP3 is a request / response SCADA protocol with typically only 1 - 2
* transactions in flight . But set a limit high enough to allow for
* some pipelining but reduce the chance of memory exhaustion
* attacks . */
static uint64_t dnp3_max_tx = 32 ;
/* Decoder event map. */
SCEnumCharMap dnp3_decoder_event_table [ ] = {
{ " FLOODED " , DNP3_DECODER_EVENT_FLOODED } ,
@ -514,7 +519,7 @@ static DNP3Transaction *DNP3TxAlloc(DNP3State *dnp3, bool request)
TAILQ_INSERT_TAIL ( & dnp3 - > tx_list , tx , next ) ;
/* Check for flood state. */
if ( dnp3 - > unreplied > DNP3_DEFAULT_REQ_FLOOD_COUNT ) {
if ( dnp3 - > unreplied > dnp3_max_tx & & ! dnp3 - > flooded ) {
DNP3SetEvent ( dnp3 , DNP3_DECODER_EVENT_FLOODED ) ;
dnp3 - > flooded = 1 ;
}
@ -1386,7 +1391,7 @@ static void DNP3StateTxFree(void *state, uint64_t tx_id)
dnp3 - > unreplied - - ;
/* Check flood state. */
if ( dnp3 - > flooded & & dnp3 - > unreplied < DNP3_DEFAULT_REQ_FLOOD_COUNT ) {
if ( dnp3 - > flooded & & dnp3 - > unreplied < dnp3_max_tx ) {
dnp3 - > flooded = 0 ;
}
@ -1432,8 +1437,7 @@ static int DNP3GetAlstateProgress(void *tx, uint8_t direction)
int retval = 0 ;
/* If flooded, "ack" old transactions. */
if ( dnp3 - > flooded & & ( dnp3 - > transaction_max -
dnp3tx - > tx_num > = DNP3_DEFAULT_REQ_FLOOD_COUNT ) ) {
if ( dnp3 - > flooded & & ( dnp3 - > transaction_max - dnp3tx - > tx_num > = dnp3_max_tx ) ) {
SCLogDebug ( " flooded: returning tx as done. " ) ;
SCReturnInt ( 1 ) ;
}
@ -1606,8 +1610,13 @@ void RegisterDNP3Parsers(void)
AppLayerParserRegisterTxDataFunc ( IPPROTO_TCP , ALPROTO_DNP3 ,
DNP3GetTxData ) ;
AppLayerParserRegisterStateDataFunc ( IPPROTO_TCP , ALPROTO_DNP3 , DNP3GetStateData ) ;
}
else {
/* Parse max-tx configuration. */
intmax_t value = 0 ;
if ( ConfGetInt ( " app-layer.protocols.dnp3.max-tx " , & value ) ) {
dnp3_max_tx = ( uint64_t ) value ;
}
} else {
SCLogConfig ( " Parser disabled for protocol %s. "
" Protocol detection still on. " , proto_name ) ;
}
@ -2254,7 +2263,7 @@ static int DNP3ParserTestFlooded(void)
FAIL_IF_NOT ( tx - > done ) ;
FAIL_IF_NOT ( DNP3GetAlstateProgress ( tx , STREAM_TOSERVER ) ) ;
for ( int i = 0 ; i < DNP3_DEFAULT_REQ_FLOOD_COUNT - 1 ; i + + ) {
for ( u int64_ t i = 0 ; i < dnp3_max_tx - 1 ; i + + ) {
SCMutexLock ( & flow . m ) ;
FAIL_IF ( AppLayerParserParse ( NULL , alp_tctx , & flow , ALPROTO_DNP3 ,
STREAM_TOSERVER , request , sizeof ( request ) ) ) ;