From 83887510a8994e0b5dfb3e4522507a3462fad58b Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 7 Oct 2021 14:31:29 +0200 Subject: [PATCH] modbus: tx iterator When there are a lot of open transactions, as is possible with modbus, the default tx_iterator will loop for the whole transacations vector to find each transaction, that means quadratic complexity. Reusing the tx_iterator from the template, and keeping as a state the last index where to start looking avoids this quadratic complexity. --- rust/src/modbus/modbus.rs | 51 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/rust/src/modbus/modbus.rs b/rust/src/modbus/modbus.rs index fa62ae7228..35147e5630 100644 --- a/rust/src/modbus/modbus.rs +++ b/rust/src/modbus/modbus.rs @@ -14,7 +14,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ -use crate::applayer::*; +use crate::applayer::{self, *}; use crate::core::{self, AppProto, ALPROTO_FAILED, ALPROTO_UNKNOWN, IPPROTO_TCP}; use std::ffi::CString; @@ -123,6 +123,27 @@ impl ModbusState { None } + fn tx_iterator( + &mut self, + min_tx_id: u64, + state: &mut u64, + ) -> Option<(&ModbusTransaction, u64, bool)> { + let mut index = *state as usize; + let len = self.transactions.len(); + + while index < len { + let tx = &self.transactions[index]; + if tx.id < min_tx_id + 1 { + index += 1; + continue; + } + *state = index as u64; + return Some((tx, tx.id - 1, (len - index) > 1)); + } + + return None; + } + /// Searches the requests in order to find one matching the given response. Returns the matching /// transaction, if it exists pub fn find_request_and_validate( @@ -362,6 +383,32 @@ pub unsafe extern "C" fn rs_modbus_state_get_tx( } } +#[no_mangle] +pub unsafe extern "C" fn rs_modbus_state_get_tx_iterator( + _ipproto: u8, + _alproto: AppProto, + state: *mut std::os::raw::c_void, + min_tx_id: u64, + _max_tx_id: u64, + istate: &mut u64, +) -> applayer::AppLayerGetTxIterTuple { + let state = cast_pointer!(state, ModbusState); + match state.tx_iterator(min_tx_id, istate) { + Some((tx, out_tx_id, has_next)) => { + let c_tx = tx as *const _ as *mut _; + let ires = applayer::AppLayerGetTxIterTuple::with_values( + c_tx, + out_tx_id, + has_next, + ); + return ires; + } + None => { + return applayer::AppLayerGetTxIterTuple::not_found(); + } + } +} + #[no_mangle] pub unsafe extern "C" fn rs_modbus_tx_get_alstate_progress( tx: *mut std::os::raw::c_void, _direction: u8, @@ -433,7 +480,7 @@ pub unsafe extern "C" fn rs_modbus_register_parser() { localstorage_new: None, localstorage_free: None, get_files: None, - get_tx_iterator: None, + get_tx_iterator: Some(rs_modbus_state_get_tx_iterator), get_de_state: rs_modbus_state_get_tx_detect_state, set_de_state: rs_modbus_state_set_tx_detect_state, get_tx_data: rs_modbus_state_get_tx_data,