// Read/Write Multiple Registers Request
assert_eq!(
modbus.parse(
+ std::ptr::null(),
&[
0x12, 0x34, // Transaction ID
0x00, 0x00, // Protocol ID
// Force Listen Only Mode
assert_eq!(
modbus.parse(
+ std::ptr::null(),
&[
0x0A, 0x00, // Transaction ID
0x00, 0x00, // Protocol ID
// Encapsulated Interface Transport (MEI)
assert_eq!(
- modbus.parse(
+ modbus.parse(std::ptr::null(),
&[
0x00, 0x10, // Transaction ID
0x00, 0x00, // Protocol ID
// Unassigned/Unknown function
assert_eq!(
- modbus.parse(
+ modbus.parse(std::ptr::null(),
&[
0x00, 0x0A, // Transaction ID
0x00, 0x00, // Protocol ID
// Read Coils request
assert_eq!(
- modbus.parse(
+ modbus.parse(std::ptr::null(),
&[
0x00, 0x00, // Transaction ID
0x00, 0x00, // Protocol ID
// Read Inputs Register request
assert_eq!(
- modbus.parse(
+ modbus.parse(std::ptr::null(),
&[
0x00, 0x0A, // Transaction ID
0x00, 0x00, // Protocol ID
// Origin: https://github.com/bro/bro/blob/master/testing/btest/Traces/modbus/modbus.trace
// Read Coils Response
assert_eq!(
- modbus.parse(
+ modbus.parse(std::ptr::null(),
&[
0x00, 0x01, // Transaction ID
0x00, 0x00, // Protocol ID
// Origin: https://github.com/bro/bro/blob/master/testing/btest/Traces/modbus/modbus.trace
// Write Single Register Response
assert_eq!(
- modbus.parse(
+ modbus.parse(std::ptr::null(),
&[
0x00, 0x01, // Transaction ID
0x00, 0x00, // Protocol ID
// Origin: https://github.com/bro/bro/blob/master/testing/btest/Traces/modbus/modbus.trace
// Write Single Register Response
assert_eq!(
- modbus.parse(
+ modbus.parse(std::ptr::null(),
&[
0x00, 0x00, // Transaction ID
0x00, 0x00, // Protocol ID
* 02110-1301, USA.
*/
use crate::applayer::{self, *};
-use crate::core::{ALPROTO_FAILED, ALPROTO_UNKNOWN, IPPROTO_TCP};
+use crate::core::*;
use crate::flow::Flow;
use std::ffi::CString;
}
}
- pub fn parse(&mut self, input: &[u8], direction: Direction) -> AppLayerResult {
+ pub fn parse(
+ &mut self, flow: *const Flow, input: &[u8], direction: Direction,
+ ) -> AppLayerResult {
let mut rest = input;
while !rest.is_empty() {
match MODBUS_PARSER.parse(rest, direction.clone()) {
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.request = Some(msg);
+ if !flow.is_null() {
+ sc_app_layer_parser_trigger_raw_stream_reassembly(
+ flow,
+ Direction::ToServer as i32,
+ );
+ }
}
None => {
let mut tx = match self.new_tx() {
tx.set_events_from_flags(&msg.error_flags);
tx.request = Some(msg);
self.transactions.push(tx);
+ if !flow.is_null() {
+ sc_app_layer_parser_trigger_raw_stream_reassembly(
+ flow,
+ Direction::ToServer as i32,
+ );
+ }
}
}
}
tx.tx_data.updated_tc = true;
tx.tx_data.updated_ts = true;
tx.response = Some(msg);
+ if !flow.is_null() {
+ sc_app_layer_parser_trigger_raw_stream_reassembly(
+ flow,
+ Direction::ToClient as i32,
+ );
+ }
}
None => {
let mut tx = match self.new_tx() {
tx.response = Some(msg);
tx.set_event(ModbusEvent::UnsolicitedResponse);
self.transactions.push(tx);
+ if !flow.is_null() {
+ sc_app_layer_parser_trigger_raw_stream_reassembly(
+ flow,
+ Direction::ToClient as i32,
+ );
+ }
}
},
}
}
unsafe extern "C" fn modbus_parse_request(
- _flow: *const Flow, state: *mut std::os::raw::c_void, pstate: *mut std::os::raw::c_void,
- stream_slice: StreamSlice,
- _data: *const std::os::raw::c_void,
+ flow: *const Flow, state: *mut std::os::raw::c_void, pstate: *mut std::os::raw::c_void,
+ stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
) -> AppLayerResult {
let buf = stream_slice.as_slice();
if buf.is_empty() {
}
let state = cast_pointer!(state, ModbusState);
- state.parse(buf, Direction::ToServer)
+ state.parse(flow, buf, Direction::ToServer)
}
unsafe extern "C" fn modbus_parse_response(
- _flow: *const Flow, state: *mut std::os::raw::c_void, pstate: *mut std::os::raw::c_void,
- stream_slice: StreamSlice,
- _data: *const std::os::raw::c_void,
+ flow: *const Flow, state: *mut std::os::raw::c_void, pstate: *mut std::os::raw::c_void,
+ stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
) -> AppLayerResult {
let buf = stream_slice.as_slice();
if buf.is_empty() {
}
let state = cast_pointer!(state, ModbusState);
- state.parse(buf, Direction::ToClient)
+ state.parse(flow, buf, Direction::ToClient)
}
#[no_mangle]
};
let ip_proto_str = CString::new("tcp").unwrap();
- if AppLayerProtoDetectConfProtoDetectionEnabledDefault(ip_proto_str.as_ptr(), parser.name, false) != 0 {
+ if AppLayerProtoDetectConfProtoDetectionEnabledDefault(
+ ip_proto_str.as_ptr(),
+ parser.name,
+ false,
+ ) != 0
+ {
let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
ALPROTO_MODBUS = alproto;
if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(RD_COILS_REQ, Direction::ToServer)
+ state.parse(std::ptr::null(), RD_COILS_REQ, Direction::ToServer)
);
assert_eq!(state.transactions.len(), 1);
assert_eq!(
AppLayerResult::ok(),
- state.parse(RD_COILS_RESP, Direction::ToClient)
+ state.parse(std::ptr::null(), RD_COILS_RESP, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(WR_MULT_REG_REQ, Direction::ToServer)
+ state.parse(std::ptr::null(), WR_MULT_REG_REQ, Direction::ToServer)
);
assert_eq!(state.transactions.len(), 1);
assert_eq!(
AppLayerResult::ok(),
- state.parse(WR_MULT_REG_RESP, Direction::ToClient)
+ state.parse(std::ptr::null(), WR_MULT_REG_RESP, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(RD_WR_MULT_REG_REQ, Direction::ToServer)
+ state.parse(std::ptr::null(), RD_WR_MULT_REG_REQ, Direction::ToServer)
);
assert_eq!(state.transactions.len(), 1);
assert_eq!(
AppLayerResult::ok(),
- state.parse(RD_WR_MULT_REG_RESP, Direction::ToClient)
+ state.parse(std::ptr::null(), RD_WR_MULT_REG_RESP, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(FORCE_LISTEN_ONLY_MODE, Direction::ToServer)
+ state.parse(
+ std::ptr::null(),
+ FORCE_LISTEN_ONLY_MODE,
+ Direction::ToServer
+ )
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(INVALID_PROTO_REQ, Direction::ToServer)
+ state.parse(std::ptr::null(), INVALID_PROTO_REQ, Direction::ToServer)
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(RD_COILS_RESP, Direction::ToClient)
+ state.parse(std::ptr::null(), RD_COILS_RESP, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::incomplete(15, 4),
- state.parse(INVALID_LEN_WR_MULT_REG_REQ, Direction::ToServer)
+ state.parse(
+ std::ptr::null(),
+ INVALID_LEN_WR_MULT_REG_REQ,
+ Direction::ToServer
+ )
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(RD_COILS_REQ, Direction::ToServer)
+ state.parse(std::ptr::null(), RD_COILS_REQ, Direction::ToServer)
);
assert_eq!(state.transactions.len(), 1);
assert_eq!(
AppLayerResult::ok(),
- state.parse(RD_COILS_ERR_RESP, Direction::ToClient)
+ state.parse(std::ptr::null(), RD_COILS_ERR_RESP, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 1);
assert_eq!(
AppLayerResult::incomplete(0, 12),
state.parse(
+ std::ptr::null(),
&RD_COILS_REQ[0..(RD_COILS_REQ.len() - 3)],
Direction::ToServer
)
assert_eq!(state.transactions.len(), 0);
assert_eq!(
AppLayerResult::ok(),
- state.parse(RD_COILS_REQ, Direction::ToServer)
+ state.parse(std::ptr::null(), RD_COILS_REQ, Direction::ToServer)
);
assert_eq!(state.transactions.len(), 1);
let resp = [RD_COILS_RESP, WR_MULT_REG_RESP].concat();
let mut state = ModbusState::new();
- assert_eq!(AppLayerResult::ok(), state.parse(&req, Direction::ToServer));
+ assert_eq!(
+ AppLayerResult::ok(),
+ state.parse(std::ptr::null(), &req, Direction::ToServer)
+ );
assert_eq!(state.transactions.len(), 2);
let tx = &state.transactions[0];
assert_eq!(
AppLayerResult::ok(),
- state.parse(&resp, Direction::ToClient)
+ state.parse(std::ptr::null(), &resp, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 2);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(EXCEEDED_LEN_WR_MULT_REG_REQ, Direction::ToServer)
+ state.parse(
+ std::ptr::null(),
+ EXCEEDED_LEN_WR_MULT_REG_REQ,
+ Direction::ToServer
+ )
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(INVALID_PDU_WR_MULT_REG_REQ, Direction::ToServer)
+ state.parse(
+ std::ptr::null(),
+ INVALID_PDU_WR_MULT_REG_REQ,
+ Direction::ToServer
+ )
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(MASK_WR_REG_REQ, Direction::ToServer)
+ state.parse(std::ptr::null(), MASK_WR_REG_REQ, Direction::ToServer)
);
assert_eq!(state.transactions.len(), 1);
assert_eq!(
AppLayerResult::ok(),
- state.parse(MASK_WR_REG_RESP, Direction::ToClient)
+ state.parse(std::ptr::null(), MASK_WR_REG_RESP, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(WR_SINGLE_REG_REQ, Direction::ToServer)
+ state.parse(std::ptr::null(), WR_SINGLE_REG_REQ, Direction::ToServer)
);
assert_eq!(state.transactions.len(), 1);
assert_eq!(
AppLayerResult::ok(),
- state.parse(WR_SINGLE_REG_RESP, Direction::ToClient)
+ state.parse(std::ptr::null(), WR_SINGLE_REG_RESP, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(INVALID_MASK_WR_REG_REQ, Direction::ToServer)
+ state.parse(
+ std::ptr::null(),
+ INVALID_MASK_WR_REG_REQ,
+ Direction::ToServer
+ )
);
assert_eq!(state.transactions.len(), 1);
assert_eq!(
AppLayerResult::ok(),
- state.parse(MASK_WR_REG_RESP, Direction::ToClient)
+ state.parse(std::ptr::null(), MASK_WR_REG_RESP, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(INVALID_WR_SINGLE_REG_REQ, Direction::ToServer)
+ state.parse(
+ std::ptr::null(),
+ INVALID_WR_SINGLE_REG_REQ,
+ Direction::ToServer
+ )
);
assert_eq!(state.transactions.len(), 1);
assert_eq!(
AppLayerResult::ok(),
- state.parse(WR_SINGLE_REG_RESP, Direction::ToClient)
+ state.parse(std::ptr::null(), WR_SINGLE_REG_RESP, Direction::ToClient)
);
assert_eq!(state.transactions.len(), 1);
let mut state = ModbusState::new();
assert_eq!(
AppLayerResult::ok(),
- state.parse(INVALID_FUNC_CODE, Direction::ToServer)
+ state.parse(std::ptr::null(), INVALID_FUNC_CODE, Direction::ToServer)
);
assert_eq!(state.transactions.len(), 1);