]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
modbus: move tests from c to rust
authorSimon Dugas <simon.dugas@cyber.gc.ca>
Fri, 19 Feb 2021 21:31:33 +0000 (16:31 -0500)
committerVictor Julien <victor@inliniac.net>
Tue, 4 May 2021 08:43:10 +0000 (10:43 +0200)
Move tests in a seperate commit so that we can use the previous one for
regression testing. This also gets rid of the temporary glue that made
the C tests work with the rust implementation.

rust/src/modbus/detect.rs
src/Makefile.am
src/app-layer-modbus.h
src/detect-engine-modbus.c [deleted file]
src/detect-engine-modbus.h [deleted file]
src/detect-modbus.c
src/detect-modbus.h
src/runmode-unittests.c

index af402f18285c735b8732a5219920e37ac7d7c582..68aa4a6642e9ac9e786aca6f0f796e32ab1bd6c2 100644 (file)
@@ -56,73 +56,6 @@ pub struct DetectModbusRust {
     value: Option<Range<u16>>,
 }
 
-/// TODO: remove these after regression testing commit
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_category(modbus: *const DetectModbusRust) -> u8 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.category.map(|val| val.bits()).unwrap_or(0)
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_function(modbus: *const DetectModbusRust) -> u8 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.function.map(|val| val as u8).unwrap_or(0)
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_subfunction(modbus: *const DetectModbusRust) -> u16 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.subfunction.unwrap_or(0)
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_has_subfunction(modbus: *const DetectModbusRust) -> bool {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.subfunction.is_some()
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_access_type(modbus: *const DetectModbusRust) -> u8 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.access_type.map(|val| val.bits()).unwrap_or(0)
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_unit_id_min(modbus: *const DetectModbusRust) -> u16 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.unit_id.as_ref().map(|val| val.start).unwrap_or(0)
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_unit_id_max(modbus: *const DetectModbusRust) -> u16 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.unit_id.as_ref().map(|val| val.end).unwrap_or(0)
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_address_min(modbus: *const DetectModbusRust) -> u16 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.address.as_ref().map(|val| val.start).unwrap_or(0)
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_address_max(modbus: *const DetectModbusRust) -> u16 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.address.as_ref().map(|val| val.end).unwrap_or(0)
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_data_min(modbus: *const DetectModbusRust) -> u16 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.value.as_ref().map(|val| val.start).unwrap_or(0)
-}
-
-#[no_mangle]
-pub extern "C" fn rs_modbus_get_data_max(modbus: *const DetectModbusRust) -> u16 {
-    let modbus = unsafe { modbus.as_ref() }.unwrap();
-    modbus.value.as_ref().map(|val| val.end).unwrap_or(0)
-}
-
 impl Default for DetectModbusRust {
     fn default() -> Self {
         DetectModbusRust {
@@ -537,3 +470,996 @@ fn parse_unit_id(unit_str: &str) -> Result<DetectModbusRust, ()> {
 
     Ok(modbus)
 }
+
+#[cfg(test)]
+mod test {
+    use super::super::modbus::ModbusState;
+    use super::*;
+    use crate::applayer::*;
+    use sawp::parser::Direction;
+
+    #[test]
+    fn test_parse() {
+        assert_eq!(
+            parse_function("function 1"),
+            Ok(DetectModbusRust {
+                function: Some(FunctionCode::RdCoils),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_function("function 8, subfunction 4"),
+            Ok(DetectModbusRust {
+                function: Some(FunctionCode::Diagnostic),
+                subfunction: Some(4),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_function("function reserved"),
+            Ok(DetectModbusRust {
+                category: Some(Flags::from(CodeCategory::RESERVED)),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_function("function !assigned"),
+            Ok(DetectModbusRust {
+                category: Some(!CodeCategory::PUBLIC_ASSIGNED),
+                ..Default::default()
+            })
+        );
+
+        assert_eq!(
+            parse_access("access read"),
+            Ok(DetectModbusRust {
+                access_type: Some(Flags::from(AccessType::READ)),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_access("access read discretes"),
+            Ok(DetectModbusRust {
+                access_type: Some(Flags::from(AccessType::READ | AccessType::DISCRETES)),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_access("access read, address 1000"),
+            Ok(DetectModbusRust {
+                access_type: Some(Flags::from(AccessType::READ)),
+                address: Some(1000..1000),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_access("access write coils, address <500"),
+            Ok(DetectModbusRust {
+                access_type: Some(Flags::from(AccessType::WRITE | AccessType::COILS)),
+                address: Some(std::u16::MIN..500),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_access("access write coils, address >500"),
+            Ok(DetectModbusRust {
+                access_type: Some(Flags::from(AccessType::WRITE | AccessType::COILS)),
+                address: Some(500..std::u16::MAX),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_access("access write holding, address 100, value <1000"),
+            Ok(DetectModbusRust {
+                access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                address: Some(100..100),
+                value: Some(std::u16::MIN..1000),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_access("access write holding, address 100, value 500<>1000"),
+            Ok(DetectModbusRust {
+                access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                address: Some(100..100),
+                value: Some(500..1000),
+                ..Default::default()
+            })
+        );
+
+        assert_eq!(
+            parse_unit_id("unit 10"),
+            Ok(DetectModbusRust {
+                unit_id: Some(10..10),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_unit_id("unit 10, function 8, subfunction 4"),
+            Ok(DetectModbusRust {
+                function: Some(FunctionCode::Diagnostic),
+                subfunction: Some(4),
+                unit_id: Some(10..10),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_unit_id("unit 10, access read, address 1000"),
+            Ok(DetectModbusRust {
+                access_type: Some(Flags::from(AccessType::READ)),
+                unit_id: Some(10..10),
+                address: Some(1000..1000),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_unit_id("unit <11"),
+            Ok(DetectModbusRust {
+                unit_id: Some(std::u16::MIN..11),
+                ..Default::default()
+            })
+        );
+        assert_eq!(
+            parse_unit_id("unit 10<>500"),
+            Ok(DetectModbusRust {
+                unit_id: Some(10..500),
+                ..Default::default()
+            })
+        );
+
+        assert_eq!(parse_access("access write holdin"), Err(()));
+        assert_eq!(parse_access("unt 10"), Err(()));
+        assert_eq!(
+            parse_access("access write holding, address 100, value 500<>"),
+            Err(())
+        );
+    }
+
+    #[test]
+    fn test_match() {
+        let mut modbus = ModbusState::new();
+
+        // Read/Write Multiple Registers Request
+        assert_eq!(
+            modbus.parse(
+                &[
+                    0x12, 0x34, // Transaction ID
+                    0x00, 0x00, // Protocol ID
+                    0x00, 0x11, // Length
+                    0x0a, // Unit ID
+                    0x17, // Function code
+                    0x00, 0x03, // Read Starting Address
+                    0x00, 0x06, // Quantity to Read
+                    0x00, 0x0E, // Write Starting Address
+                    0x00, 0x03, // Quantity to Write
+                    0x06, // Write Byte count
+                    0x12, 0x34, // Write Registers Value
+                    0x56, 0x78, 0x9A, 0xBC
+                ],
+                Direction::ToServer
+            ),
+            AppLayerResult::ok()
+        );
+        assert_eq!(modbus.transactions.len(), 1);
+        // function 23
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    function: Some(FunctionCode::RdWrMultRegs),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 15, value <4660
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(15..15),
+                    value: Some(std::u16::MIN..4660),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 15, value 4661
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(15..15),
+                    value: Some(4661..4661),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 16, value 20000<>22136
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(16..16),
+                    value: Some(20000..22136),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 16, value 22136<>30000
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(16..16),
+                    value: Some(22136..30000),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 15, value >4660
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(15..15),
+                    value: Some(4660..std::u16::MAX),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 16, value <22137
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(16..16),
+                    value: Some(std::u16::MIN..22137),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 16, value <22137
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(16..16),
+                    value: Some(std::u16::MIN..22137),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 17, value 39612
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(17..17),
+                    value: Some(39612..39612),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 17, value 30000<>39613
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(17..17),
+                    value: Some(30000..39613),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 15, value 4659<>5000
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(15..15),
+                    value: Some(4659..5000),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write holding, address 17, value >39611
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE | AccessType::HOLDING)),
+                    address: Some(17..17),
+                    value: Some(39611..std::u16::MAX),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 12
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    unit_id: Some(12..12),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 5<>9
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    unit_id: Some(5..9),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 11<>15
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    unit_id: Some(11..15),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit >11
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    unit_id: Some(11..std::u16::MAX),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit <9
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    unit_id: Some(std::u16::MIN..9),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 10
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    unit_id: Some(10..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 5<>15
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    unit_id: Some(5..15),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit >9
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    unit_id: Some(9..std::u16::MAX),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit <11
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    unit_id: Some(std::u16::MIN..11),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 10, function 20
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    function: Some(FunctionCode::RdFileRec),
+                    unit_id: Some(10..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 11, function 20
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    function: Some(FunctionCode::RdFileRec),
+                    unit_id: Some(11..11),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 11, function 23
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    function: Some(FunctionCode::RdWrMultRegs),
+                    unit_id: Some(11..11),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 11, function public
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    category: Some(Flags::from(
+                        CodeCategory::PUBLIC_ASSIGNED | CodeCategory::PUBLIC_UNASSIGNED
+                    )),
+                    unit_id: Some(11..11),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 10, function user
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    category: Some(Flags::from(CodeCategory::USER_DEFINED)),
+                    unit_id: Some(10..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 10, function 23
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    function: Some(FunctionCode::RdWrMultRegs),
+                    unit_id: Some(10..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 10, function public
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    category: Some(Flags::from(
+                        CodeCategory::PUBLIC_ASSIGNED | CodeCategory::PUBLIC_UNASSIGNED
+                    )),
+                    unit_id: Some(10..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 10, function !user
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[0],
+                &DetectModbusRust {
+                    category: Some(!CodeCategory::USER_DEFINED),
+                    unit_id: Some(10..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+
+        // Force Listen Only Mode
+        assert_eq!(
+            modbus.parse(
+                &[
+                    0x0A, 0x00, // Transaction ID
+                    0x00, 0x00, // Protocol ID
+                    0x00, 0x06, // Length
+                    0x00, // Unit ID
+                    0x08, // Function code
+                    0x00, 0x04, // Sub-function code
+                    0x00, 0x00 // Data
+                ],
+                Direction::ToServer
+            ),
+            AppLayerResult::ok()
+        );
+        assert_eq!(modbus.transactions.len(), 2);
+        // function 8, subfunction 4
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[1],
+                &DetectModbusRust {
+                    function: Some(FunctionCode::Diagnostic),
+                    subfunction: Some(4),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+
+        // Encapsulated Interface Transport (MEI)
+        assert_eq!(
+            modbus.parse(
+                &[
+                    0x00, 0x10, // Transaction ID
+                    0x00, 0x00, // Protocol ID
+                    0x00, 0x05, // Length
+                    0x00, // Unit ID
+                    0x2B, // Function code
+                    0x0F, // MEI Type
+                    0x00, 0x00 // Data
+                ],
+                Direction::ToServer
+            ),
+            AppLayerResult::ok()
+        );
+        assert_eq!(modbus.transactions.len(), 3);
+        // function reserved
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[2],
+                &DetectModbusRust {
+                    category: Some(Flags::from(CodeCategory::RESERVED)),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+
+        // Unassigned/Unknown function
+        assert_eq!(
+            modbus.parse(
+                &[
+                    0x00, 0x0A, // Transaction ID
+                    0x00, 0x00, // Protocol ID
+                    0x00, 0x02, // Length
+                    0x00, // Unit ID
+                    0x12  // Function code
+                ],
+                Direction::ToServer
+            ),
+            AppLayerResult::ok()
+        );
+        assert_eq!(modbus.transactions.len(), 4);
+        // function !assigned
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[3],
+                &DetectModbusRust {
+                    category: Some(!CodeCategory::PUBLIC_ASSIGNED),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+
+        // Read Coils request
+        assert_eq!(
+            modbus.parse(
+                &[
+                    0x00, 0x00, // Transaction ID
+                    0x00, 0x00, // Protocol ID
+                    0x00, 0x06, // Length
+                    0x0a, // Unit ID
+                    0x01, // Function code
+                    0x78, 0x90, // Starting Address
+                    0x00, 0x13 // Quantity of coils
+                ],
+                Direction::ToServer
+            ),
+            AppLayerResult::ok()
+        );
+        assert_eq!(modbus.transactions.len(), 5);
+        // access read
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[4],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ)),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read, address 30870
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[4],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ)),
+                    address: Some(30870..30870),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 10, access read, address 30863
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[4],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ)),
+                    unit_id: Some(10..10),
+                    address: Some(30863..30863),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 11, access read, address 30870
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[4],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ)),
+                    unit_id: Some(11..11),
+                    address: Some(30870..30870),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 11, access read, address 30863
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[4],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ)),
+                    unit_id: Some(11..11),
+                    address: Some(30863..30863),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 10, access write
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[4],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE)),
+                    unit_id: Some(10..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // unit 10, access read, address 30870
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[4],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ)),
+                    unit_id: Some(10..10),
+                    address: Some(30870..30870),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+
+        // Read Inputs Register request
+        assert_eq!(
+            modbus.parse(
+                &[
+                    0x00, 0x0A, // Transaction ID
+                    0x00, 0x00, // Protocol ID
+                    0x00, 0x06, // Length
+                    0x00, // Unit ID
+                    0x04, // Function code
+                    0x00, 0x08, // Starting Address
+                    0x00, 0x60 // Quantity of Registers
+                ],
+                Direction::ToServer
+            ),
+            AppLayerResult::ok()
+        );
+        assert_eq!(modbus.transactions.len(), 6);
+        // access read input
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address <9
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(std::u16::MIN..9),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address 5<>9
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(5..9),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address >104
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(104..std::u16::MAX),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address 104<>110
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(104..110),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address 9
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(9..9),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address <10
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(std::u16::MIN..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address 5<>10
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(5..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address >103
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(103..std::u16::MAX),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address 103<>110
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(103..110),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read input, address 104
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[5],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ | AccessType::INPUT)),
+                    address: Some(104..104),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+
+        // Origin: https://github.com/bro/bro/blob/master/testing/btest/Traces/modbus/modbus.trace
+        // Read Coils Response
+        assert_eq!(
+            modbus.parse(
+                &[
+                    0x00, 0x01, // Transaction ID
+                    0x00, 0x00, // Protocol ID
+                    0x00, 0x04, // Length
+                    0x0a, // Unit ID
+                    0x01, // Function code
+                    0x01, // Count
+                    0x00, // Data
+                ],
+                Direction::ToClient
+            ),
+            AppLayerResult::ok()
+        );
+        assert_eq!(modbus.transactions.len(), 7);
+        // function 1
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[6],
+                &DetectModbusRust {
+                    function: Some(FunctionCode::RdCoils),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read, address 104
+        // Fails because there was no request, and the address is not retrievable
+        // from the response.
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[6],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ)),
+                    address: Some(104..104),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+
+        // Origin: https://github.com/bro/bro/blob/master/testing/btest/Traces/modbus/modbus.trace
+        // Write Single Register Response
+        assert_eq!(
+            modbus.parse(
+                &[
+                    0x00, 0x01, // Transaction ID
+                    0x00, 0x00, // Protocol ID
+                    0x00, 0x06, // Length
+                    0x0a, // Unit ID
+                    0x06, // Function code
+                    0x00, 0x05, // Starting address
+                    0x00, 0x0b // Data
+                ],
+                Direction::ToClient
+            ),
+            AppLayerResult::ok()
+        );
+        assert_eq!(modbus.transactions.len(), 8);
+        // function 6
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[7],
+                &DetectModbusRust {
+                    function: Some(FunctionCode::WrSingleReg),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access write, address 10
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[7],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::WRITE)),
+                    address: Some(10..10),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+
+        // Origin: https://github.com/bro/bro/blob/master/testing/btest/Traces/modbus/modbus.trace
+        // Write Single Register Response
+        assert_eq!(
+            modbus.parse(
+                &[
+                    0x00, 0x00, // Transaction ID
+                    0x00, 0x00, // Protocol ID
+                    0x00, 0x06, // Length
+                    0x0a, // Unit ID
+                    0x08, // Function code
+                    0x00, 0x0a, // Diagnostic code
+                    0x00, 0x00 // Data
+                ],
+                Direction::ToClient
+            ),
+            AppLayerResult::ok()
+        );
+        assert_eq!(modbus.transactions.len(), 9);
+        // function 8
+        assert_eq!(
+            rs_modbus_inspect(
+                &modbus.transactions[8],
+                &DetectModbusRust {
+                    function: Some(FunctionCode::Diagnostic),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+        // access read
+        assert_ne!(
+            rs_modbus_inspect(
+                &modbus.transactions[8],
+                &DetectModbusRust {
+                    access_type: Some(Flags::from(AccessType::READ)),
+                    ..Default::default()
+                }
+            ),
+            1
+        );
+    }
+}
index 468da030b9754c0557f60b624b3ea904a62e80dc..246249f5558dd2219ebabac28b3b54bb18644561 100755 (executable)
@@ -143,7 +143,6 @@ noinst_HEADERS = \
        detect-engine.h \
        detect-engine-iponly.h \
        detect-engine-loader.h \
-       detect-engine-modbus.h \
        detect-engine-mpm.h \
        detect-engine-payload.h \
        detect-engine-port.h \
@@ -722,7 +721,6 @@ libsuricata_c_a_SOURCES = \
        detect-engine-file.c \
        detect-engine-iponly.c \
        detect-engine-loader.c \
-       detect-engine-modbus.c \
        detect-engine-mpm.c \
        detect-engine-payload.c \
        detect-engine-port.c \
index 5d97fdcedef5d651ab2d1c68312152a7b1e2decf..04a12bcee9ebf8cc2c851ccbc514315f7e9a7afe 100644 (file)
 #ifndef __APP_LAYER_MODBUS_H__
 #define __APP_LAYER_MODBUS_H__
 
-/* Modbus Function Code Categories. */
-#define MODBUS_CAT_NONE                 0x0
-#define MODBUS_CAT_PUBLIC_ASSIGNED      (1<<0)
-#define MODBUS_CAT_PUBLIC_UNASSIGNED    (1<<1)
-#define MODBUS_CAT_USER_DEFINED         (1<<2)
-#define MODBUS_CAT_RESERVED             (1<<3)
-#define MODBUS_CAT_ALL                  0xFF
-
-/* Modbus Read/Write function and Access Types. */
-#define MODBUS_TYP_NONE                 0x0
-#define MODBUS_TYP_ACCESS_MASK          0x03
-#define MODBUS_TYP_READ                 (1<<0)
-#define MODBUS_TYP_WRITE                (1<<1)
-#define MODBUS_TYP_ACCESS_FUNCTION_MASK 0x3C
-#define MODBUS_TYP_BIT_ACCESS_MASK      0x0C
-#define MODBUS_TYP_DISCRETES            (1<<2)
-#define MODBUS_TYP_COILS                (1<<3)
-#define MODBUS_TYP_WORD_ACCESS_MASK     0x30
-#define MODBUS_TYP_INPUT                (1<<4)
-#define MODBUS_TYP_HOLDING              (1<<5)
-#define MODBUS_TYP_SINGLE               (1<<6)
-#define MODBUS_TYP_MULTIPLE             (1<<7)
-#define MODBUS_TYP_WRITE_SINGLE         (MODBUS_TYP_WRITE | MODBUS_TYP_SINGLE)
-#define MODBUS_TYP_WRITE_MULTIPLE       (MODBUS_TYP_WRITE | MODBUS_TYP_MULTIPLE)
-#define MODBUS_TYP_READ_WRITE_MULTIPLE  (MODBUS_TYP_READ | MODBUS_TYP_WRITE | MODBUS_TYP_MULTIPLE)
-
 void RegisterModbusParsers(void);
 
 #endif /* __APP_LAYER_MODBUS_H__ */
diff --git a/src/detect-engine-modbus.c b/src/detect-engine-modbus.c
deleted file mode 100644 (file)
index 354a73c..0000000
+++ /dev/null
@@ -1,1237 +0,0 @@
-/*
- * Copyright (C) 2014 ANSSI
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** \file
- *
- *  \author David DIALLO <diallo@et.esiea.fr>
- *
- *  Based on detect-engine-dns.c
- */
-
-#include "suricata-common.h"
-
-#include "app-layer.h"
-
-#include "detect.h"
-#include "detect-modbus.h"
-
-#include "detect-engine-modbus.h"
-
-#include "flow.h"
-
-#include "util-debug.h"
-
-#ifdef UNITTESTS /* UNITTESTS */
-#include "app-layer-parser.h"
-
-#include "detect-parse.h"
-
-#include "detect-engine.h"
-
-#include "flow-util.h"
-
-#include "stream-tcp.h"
-
-#include "util-unittest.h"
-#include "util-unittest-helper.h"
-
-/* Modbus Application Protocol Specification V1.1b3 6.1: Read Coils */
-/* Example of a request to read discrete outputs 20-38 */
-static uint8_t readCoilsReq[] = {/* Transaction ID */    0x00, 0x00,
-                                 /* Protocol ID */       0x00, 0x00,
-                                 /* Length */            0x00, 0x06,
-                                 /* Unit ID */           0x0a,
-                                 /* Function code */     0x01,
-                                 /* Starting Address */  0x78, 0x90,
-                                 /* Quantity of coils */ 0x00, 0x13 };
-
-/* Modbus Application Protocol Specification V1.1b3 6.4: Read Input Registers */
-/* Example of a request to read input register 9 */
-static uint8_t readInputsRegistersReq[] = {/* Transaction ID */          0x00, 0x0A,
-                                           /* Protocol ID */             0x00, 0x00,
-                                           /* Length */                  0x00, 0x06,
-                                           /* Unit ID */                 0x00,
-                                           /* Function code */           0x04,
-                                           /* Starting Address */        0x00, 0x08,
-                                           /* Quantity of Registers */   0x00, 0x60};
-
-/* Modbus Application Protocol Specification V1.1b3 6.17: Read/Write Multiple registers */
-/* Example of a request to read six registers starting at register 4, */
-/* and to write three registers starting at register 15 */
-static uint8_t readWriteMultipleRegistersReq[] = {/* Transaction ID */          0x12, 0x34,
-                                                  /* Protocol ID */             0x00, 0x00,
-                                                  /* Length */                  0x00, 0x11,
-                                                  /* Unit ID */                 0x0a,
-                                                  /* Function code */           0x17,
-                                                  /* Read Starting Address */   0x00, 0x03,
-                                                  /* Quantity to Read */        0x00, 0x06,
-                                                  /* Write Starting Address */  0x00, 0x0E,
-                                                  /* Quantity to Write */       0x00, 0x03,
-                                                  /* Write Byte count */        0x06,
-                                                  /* Write Registers Value */   0x12, 0x34, /* 15 */
-                                                                                0x56, 0x78, /* 16 */
-                                                                                0x9A, 0xBC};/* 17 */
-
-/* Modbus Application Protocol Specification V1.1b3 6.8.1: 04 Force Listen Only Mode */
-/* Example of a request to to remote device to its Listen Only MOde for Modbus Communications. */
-static uint8_t forceListenOnlyMode[] = {/* Transaction ID */     0x0A, 0x00,
-                                        /* Protocol ID */        0x00, 0x00,
-                                        /* Length */             0x00, 0x06,
-                                        /* Unit ID */            0x00,
-                                        /* Function code */      0x08,
-                                        /* Sub-function code */  0x00, 0x04,
-                                        /* Data */               0x00, 0x00};
-
-/* Modbus Application Protocol Specification V1.1b3 Annex A */
-/* Modbus Reserved Function codes, Subcodes and MEI types */
-static uint8_t encapsulatedInterfaceTransport[] = {
-                                        /* Transaction ID */     0x00, 0x10,
-                                        /* Protocol ID */        0x00, 0x00,
-                                        /* Length */             0x00, 0x05,
-                                        /* Unit ID */            0x00,
-                                        /* Function code */      0x2B,
-                                        /* MEI Type */           0x0F,
-                                        /* Data */               0x00, 0x00};
-
-static uint8_t unassigned[] = {
-    /* Transaction ID */ 0x00, 0x0A,
-    /* Protocol ID */ 0x00, 0x00,
-    /* Length */ 0x00, 0x02,
-    /* Unit ID */ 0x00,
-    /* Function code */ 0x3F
-};
-
-/** \test Test code function. */
-static int DetectEngineInspectModbusTest01(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-    s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                            "(msg:\"Testing modbus code function\"; "
-                                            "modbus: function 23; sid:1;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER,
-                                readWriteMultipleRegistersReq,
-                                sizeof(readWriteMultipleRegistersReq));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 1));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test code function and code subfunction. */
-static int DetectEngineInspectModbusTest02(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                           "(msg:\"Testing modbus function and subfunction\"; "
-                                           "modbus: function 8, subfunction 4;  sid:1;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER, forceListenOnlyMode,
-                                sizeof(forceListenOnlyMode));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 1));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test function category. */
-static int DetectEngineInspectModbusTest03(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                           "(msg:\"Testing modbus category function\"; "
-                                           "modbus: function reserved;  sid:1;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER,
-                                encapsulatedInterfaceTransport,
-                                sizeof(encapsulatedInterfaceTransport));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 1));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test negative function category. */
-static int DetectEngineInspectModbusTest04(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus category function\"; "
-                                       "modbus: function !assigned;  sid:1;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER, unassigned,
-                                sizeof(unassigned));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 1));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test access type. */
-static int DetectEngineInspectModbusTest05(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                           "(msg:\"Testing modbus access type\"; "
-                                           "modbus: access read;  sid:1;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER, readCoilsReq,
-                                sizeof(readCoilsReq));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 1));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test access function. */
-static int DetectEngineInspectModbusTest06(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                           "(msg:\"Testing modbus access type\"; "
-                                           "modbus: access read input;  sid:1;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER, readInputsRegistersReq,
-                                sizeof(readInputsRegistersReq));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 1));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test read access at an address. */
-static int DetectEngineInspectModbusTest07(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                           "(msg:\"Testing modbus address access\"; "
-                                           "modbus: access read, address 30870;  sid:1;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER, readCoilsReq,
-                                sizeof(readCoilsReq));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 1));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test read access at a range of address. */
-static int DetectEngineInspectModbusTest08(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    /* readInputsRegistersReq, Starting Address = 0x08, Quantity of Registers = 0x60 */
-    /* Read access address from 9 to 104 */
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address <9;  sid:1;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address 9;  sid:2;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address 5<>9;  sid:3;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address <10;  sid:4;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address 5<>10;  sid:5;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address >103;  sid:6;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address 103<>110;  sid:7;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address 104;  sid:8;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address >104;  sid:9;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus access\"; "
-                                      "modbus: access read input, "
-                                      "address 104<>110;  sid:10;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER, readInputsRegistersReq,
-                                sizeof(readInputsRegistersReq));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF(PacketAlertCheck(p, 1));
-    FAIL_IF(PacketAlertCheck(p, 3));
-    FAIL_IF(PacketAlertCheck(p, 9));
-    FAIL_IF(PacketAlertCheck(p, 10));
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 2));
-    FAIL_IF_NOT(PacketAlertCheck(p, 4));
-    FAIL_IF_NOT(PacketAlertCheck(p, 5));
-    FAIL_IF_NOT(PacketAlertCheck(p, 6));
-    FAIL_IF_NOT(PacketAlertCheck(p, 7));
-    FAIL_IF_NOT(PacketAlertCheck(p, 8));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test write access at a address in a range of value. */
-static int DetectEngineInspectModbusTest09(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    /* readWriteMultipleRegistersReq, Write Starting Address = 0x0E, Quantity to Write = 0x03 */
-    /* Write access register address 15 = 0x1234 (4660)     */
-    /* Write access register address 16 = 0x5678 (22136)    */
-    /* Write access register address 17 = 0x9ABC (39612)    */
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 15, value <4660;  sid:1;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 16, value <22137;  sid:2;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 17, value 39612;  sid:3;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 15, value 4661;  sid:4;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 16, value 20000<>22136;  sid:5;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 17, value 30000<>39613;  sid:6;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 15, value 4659<>5000;  sid:7;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 16, value 22136<>30000;  sid:8;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 17, value >39611;  sid:9;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                                      "(msg:\"Testing modbus write access\"; "
-                                      "modbus: access write holding, "
-                                      "address 15, value >4660;  sid:10;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER,
-                                readWriteMultipleRegistersReq,
-                                sizeof(readWriteMultipleRegistersReq));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF(PacketAlertCheck(p, 1));
-    FAIL_IF(PacketAlertCheck(p, 4));
-    FAIL_IF(PacketAlertCheck(p, 5));
-    FAIL_IF(PacketAlertCheck(p, 8));
-    FAIL_IF(PacketAlertCheck(p, 10));
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 2));
-    FAIL_IF_NOT(PacketAlertCheck(p, 3));
-    FAIL_IF_NOT(PacketAlertCheck(p, 6));
-    FAIL_IF_NOT(PacketAlertCheck(p, 7));
-    FAIL_IF_NOT(PacketAlertCheck(p, 9));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test Test code unit_id. */
-static int DetectEngineInspectModbusTest10(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readWriteMultipleRegistersReq,
-                       sizeof(readWriteMultipleRegistersReq),
-                       IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    /* readWriteMultipleRegistersReq, Write Starting Address = 0x0E, Quantity to Write = 0x03 */
-    /* Unit ID                          = 0x0a (10)         */
-    /* Function code                    = 0x17 (23)         */
-    /* Write access register address 15 = 0x1234 (4660)     */
-    /* Write access register address 16 = 0x5678 (22136)    */
-    /* Write access register address 17 = 0x9ABC (39612)    */
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 10; sid:1;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 12; sid:2;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 5<>15; sid:3;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 5<>9; sid:4;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 11<>15; sid:5;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit >9; sid:6;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit >11; sid:7;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit <11; sid:8;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit <9; sid:9;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER,
-                                readWriteMultipleRegistersReq,
-                                sizeof(readWriteMultipleRegistersReq));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF(PacketAlertCheck(p, 2));
-    FAIL_IF(PacketAlertCheck(p, 4));
-    FAIL_IF(PacketAlertCheck(p, 5));
-    FAIL_IF(PacketAlertCheck(p, 7));
-    FAIL_IF(PacketAlertCheck(p, 9));
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 1));
-    FAIL_IF_NOT(PacketAlertCheck(p, 3));
-    FAIL_IF_NOT(PacketAlertCheck(p, 6));
-    FAIL_IF_NOT(PacketAlertCheck(p, 8));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test Test code unit_id and code function. */
-static int DetectEngineInspectModbusTest11(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readWriteMultipleRegistersReq,
-                       sizeof(readWriteMultipleRegistersReq),
-                       IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    /* readWriteMultipleRegistersReq, Write Starting Address = 0x0E, Quantity to Write = 0x03 */
-    /* Unit ID                          = 0x0a (10)         */
-    /* Function code                    = 0x17 (23)         */
-    /* Write access register address 15 = 0x1234 (4660)     */
-    /* Write access register address 16 = 0x5678 (22136)    */
-    /* Write access register address 17 = 0x9ABC (39612)    */
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 10, function 20; sid:1;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 10, function 23; sid:2;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 11, function 20; sid:3;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 11, function 23; sid:4;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 10, function public; sid:5;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 11, function public; sid:6;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 10, function user; sid:7;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus code unit_id\"; "
-                              "modbus: unit 10, function !user; sid:8;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER,
-                                readWriteMultipleRegistersReq,
-                                sizeof(readWriteMultipleRegistersReq));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF(PacketAlertCheck(p, 1));
-    FAIL_IF(PacketAlertCheck(p, 3));
-    FAIL_IF(PacketAlertCheck(p, 4));
-    FAIL_IF(PacketAlertCheck(p, 6));
-    FAIL_IF(PacketAlertCheck(p, 7));
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 2));
-    FAIL_IF_NOT(PacketAlertCheck(p, 5));
-    FAIL_IF_NOT(PacketAlertCheck(p, 8));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-
-/** \test unit_id and read access at an address. */
-static int DetectEngineInspectModbusTest12(void)
-{
-    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
-    DetectEngineThreadCtx *det_ctx = NULL;
-    DetectEngineCtx *de_ctx = NULL;
-    Flow f;
-    Packet *p = NULL;
-    Signature *s = NULL;
-    TcpSession ssn;
-    ThreadVars tv;
-
-    FAIL_IF_NULL(alp_tctx);
-
-    memset(&tv, 0, sizeof(ThreadVars));
-    memset(&f, 0, sizeof(Flow));
-    memset(&ssn, 0, sizeof(TcpSession));
-
-    p = UTHBuildPacket(readCoilsReq, sizeof(readCoilsReq), IPPROTO_TCP);
-
-    FLOW_INITIALIZE(&f);
-    f.alproto   = ALPROTO_MODBUS;
-    f.protoctx  = (void *)&ssn;
-    f.proto     = IPPROTO_TCP;
-    f.flags     |= FLOW_IPV4;
-
-    p->flow         = &f;
-    p->flags        |= PKT_HAS_FLOW | PKT_STREAM_EST;
-    p->flowflags    |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
-
-    StreamTcpInitConfig(true);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    /* readCoilsReq, Read coils Starting Address = 0x7890 (30864), Quantity of coils = 0x13 (19) */
-    /* Unit ID              = 0x0a (10) */
-    /* Function code        = 0x01 (01) */
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus address access\"; "
-                              "modbus: unit 10, access read, address 30870;  sid:1;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus address access\"; "
-                              "modbus: unit 10, access read, address 30863;  sid:2;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus address access\"; "
-                              "modbus: unit 11, access read, address 30870;  sid:3;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus address access\"; "
-                              "modbus: unit 11, access read, address 30863;  sid:4;)");
-
-    s = DetectEngineAppendSig(de_ctx, "alert modbus any any -> any any "
-                              "(msg:\"Testing modbus address access\"; "
-                              "modbus: unit 10, access write;  sid:5;)");
-    FAIL_IF_NULL(s);
-
-    SigGroupBuild(de_ctx);
-    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
-
-    FLOWLOCK_WRLOCK(&f);
-    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS,
-                                STREAM_TOSERVER, readCoilsReq,
-                                sizeof(readCoilsReq));
-    FAIL_IF_NOT(r == 0);
-    FLOWLOCK_UNLOCK(&f);
-
-    FAIL_IF_NULL(f.alstate);
-
-    /* do detect */
-    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
-
-    FAIL_IF(PacketAlertCheck(p, 2));
-    FAIL_IF(PacketAlertCheck(p, 3));
-    FAIL_IF(PacketAlertCheck(p, 4));
-    FAIL_IF(PacketAlertCheck(p, 5));
-
-    FAIL_IF_NOT(PacketAlertCheck(p, 1));
-
-    AppLayerParserThreadCtxFree(alp_tctx);
-    DetectEngineThreadCtxDeinit(&tv, det_ctx);
-    SigGroupCleanup(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-
-    StreamTcpFreeConfig(true);
-    FLOW_DESTROY(&f);
-    UTHFreePacket(p);
-    PASS;
-}
-#endif /* UNITTESTS */
-
-void DetectEngineInspectModbusRegisterTests(void)
-{
-#ifdef UNITTESTS
-    UtRegisterTest("DetectEngineInspectModbusTest01 - Code function",
-                   DetectEngineInspectModbusTest01);
-    UtRegisterTest("DetectEngineInspectModbusTest02 - code function and code subfunction",
-                   DetectEngineInspectModbusTest02);
-    UtRegisterTest("DetectEngineInspectModbusTest03 - Function category",
-                   DetectEngineInspectModbusTest03);
-    UtRegisterTest("DetectEngineInspectModbusTest04 - Negative function category",
-                   DetectEngineInspectModbusTest04);
-    UtRegisterTest("DetectEngineInspectModbusTest05 - Access type",
-                   DetectEngineInspectModbusTest05);
-    UtRegisterTest("DetectEngineInspectModbusTest06 - Access function",
-                   DetectEngineInspectModbusTest06);
-    UtRegisterTest("DetectEngineInspectModbusTest07 - Read access at an address",
-                   DetectEngineInspectModbusTest07);
-    UtRegisterTest("DetectEngineInspectModbusTest08 - Read access at a range of address",
-                   DetectEngineInspectModbusTest08);
-    UtRegisterTest("DetectEngineInspectModbusTest09 - Write access at an address a range of value",
-                   DetectEngineInspectModbusTest09);
-    UtRegisterTest("DetectEngineInspectModbusTest10 - Code unit_id",
-                   DetectEngineInspectModbusTest10);
-    UtRegisterTest("DetectEngineInspectModbusTest11 - Code unit_id and code function",
-                   DetectEngineInspectModbusTest11);
-    UtRegisterTest("DetectEngineInspectModbusTest12 - Code unit_id and acces function",
-                   DetectEngineInspectModbusTest12);
-#endif /* UNITTESTS */
-    return;
-}
diff --git a/src/detect-engine-modbus.h b/src/detect-engine-modbus.h
deleted file mode 100644 (file)
index 5881fa7..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2014 ANSSI
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** \file
- *
- *  \author David DIALLO <diallo@et.esiea.fr>
- */
-
-#ifndef __DETECT_ENGINE_MODBUS_H__
-#define __DETECT_ENGINE_MODBUS_H__
-
-int DetectEngineInspectModbus(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *,
-        const struct DetectEngineAppInspectionEngine_ *engine, const Signature *, Flow *, uint8_t,
-        void *, void *, uint64_t);
-
-void DetectEngineInspectModbusRegisterTests(void);
-#endif /* __DETECT_ENGINE_MODBUS_H__ */
index 0fe6d345f845009f57a158ebd84f815b0c039f54..6603ffbf3767d689e465ae1fb2b6dbd5ebdbe7c7 100644 (file)
@@ -52,8 +52,6 @@
 #include "util-debug.h"
 #include "util-byte.h"
 
-#include "app-layer-modbus.h"
-
 #include "stream-tcp.h"
 #include "rust.h"
 
@@ -170,502 +168,170 @@ void DetectModbusRegister(void)
 }
 
 #ifdef UNITTESTS /* UNITTESTS */
-#include "util-unittest.h"
-
-/** Convert rust structure to C for regression tests.
- *
- * Note: Newly allocated `DetectModbus` structure must be freed.
- *
- * TODO: remove this after regression testing commit.
- */
-static DetectModbusValue *DetectModbusValueRustToC(uint16_t min, uint16_t max)
-{
-    DetectModbusValue *value = SCMalloc(sizeof(*value));
-    FAIL_IF_NULL(value);
-
-    value->min = min;
-    value->max = max;
-
-    if (min == max) {
-        value->mode = DETECT_MODBUS_EQ;
-    } else if (min == 0) {
-        value->mode = DETECT_MODBUS_LT;
-    } else if (max == UINT16_MAX) {
-        value->mode = DETECT_MODBUS_GT;
-    } else {
-        value->mode = DETECT_MODBUS_RA;
-    }
-
-    return value;
-}
-
-static DetectModbus *DetectModbusRustToC(DetectModbusRust *ctx)
-{
-    DetectModbus *modbus = SCMalloc(sizeof(*modbus));
-    FAIL_IF_NULL(modbus);
-
-    modbus->category = rs_modbus_get_category(ctx);
-    modbus->function = rs_modbus_get_function(ctx);
-    modbus->subfunction = rs_modbus_get_subfunction(ctx);
-    modbus->has_subfunction = rs_modbus_get_has_subfunction(ctx);
-    modbus->type = rs_modbus_get_access_type(ctx);
-
-    modbus->unit_id = DetectModbusValueRustToC(
-            rs_modbus_get_unit_id_min(ctx), rs_modbus_get_unit_id_max(ctx));
-
-    modbus->address = DetectModbusValueRustToC(
-            rs_modbus_get_address_min(ctx), rs_modbus_get_address_max(ctx));
-
-    modbus->data =
-            DetectModbusValueRustToC(rs_modbus_get_data_min(ctx), rs_modbus_get_data_max(ctx));
-
-    return modbus;
-}
-
-static void DetectModbusCFree(DetectModbus *modbus)
-{
-    if (modbus) {
-        if (modbus->unit_id)
-            SCFree(modbus->unit_id);
-
-        if (modbus->address)
-            SCFree(modbus->address);
-
-        if (modbus->data)
-            SCFree(modbus->data);
-
-        SCFree(modbus);
-    }
-}
-
-/** \test Signature containing a function. */
-static int DetectModbusTest01(void)
-{
-    DetectEngineCtx *de_ctx = NULL;
-    DetectModbus    *modbus = NULL;
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus function\"; "
-                                       "modbus: function 1;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+#include "app-layer-parser.h"
 
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+#include "flow-util.h"
 
-    FAIL_IF_NOT(modbus->function == 1);
-
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-    PASS;
-}
+#include "util-unittest.h"
+#include "util-unittest-helper.h"
 
-/** \test Signature containing a function and a subfunction. */
-static int DetectModbusTest02(void)
+/**
+ * Sample data for tests derived from
+ * https://github.com/bro/bro/blob/master/testing/btest/Traces/modbus/modbus.trace
+ */
+static uint8_t writeSingleCoil[] = {
+    /* Transaction ID */ 0x00, 0x01,
+    /* Protocol ID */ 0x00, 0x00,
+    /* Length */ 0x00, 0x06,
+    /* Unit ID */ 0x0a,
+    /* Function code */ 0x05,
+    /* Read Starting Address */ 0x00, 0x02,
+    /* Data */ 0x00, 0x00
+};
+
+static uint8_t restartCommOption[] = {
+    /* Transaction ID */ 0x00, 0x00,
+    /* Protocol ID */ 0x00, 0x00,
+    /* Length */ 0x00, 0x06,
+    /* Unit ID */ 0x0a,
+    /* Function code */ 0x08,
+    /* Diagnostic Code */ 0x00, 0x01,
+    /* Data */ 0x00, 0x00
+};
+
+/** \test Signature containing an access type. */
+static int DetectModbusTestAccess(void)
 {
+    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+    DetectEngineThreadCtx *det_ctx = NULL;
     DetectEngineCtx *de_ctx = NULL;
-    DetectModbus    *modbus = NULL;
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
+    Flow f;
+    Packet *p = NULL;
+    Signature *s = NULL;
+    TcpSession ssn;
+    ThreadVars tv;
 
-    de_ctx->flags |= DE_QUIET;
+    FAIL_IF_NULL(alp_tctx);
 
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus function and subfunction\"; "
-                                       "modbus: function 8, subfunction 4;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+    memset(&tv, 0, sizeof(ThreadVars));
+    memset(&f, 0, sizeof(Flow));
+    memset(&ssn, 0, sizeof(TcpSession));
 
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+    p = UTHBuildPacket(restartCommOption, sizeof(restartCommOption), IPPROTO_TCP);
 
-    FAIL_IF_NOT(modbus->function == 8);
-    FAIL_IF_NOT(modbus->subfunction == 4);
+    FLOW_INITIALIZE(&f);
+    f.alproto = ALPROTO_MODBUS;
+    f.protoctx = (void *)&ssn;
+    f.proto = IPPROTO_TCP;
+    f.flags |= FLOW_IPV4;
 
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-    PASS;
-}
+    p->flow = &f;
+    p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+    p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
 
-/** \test Signature containing a function category. */
-static int DetectModbusTest03(void)
-{
-    DetectEngineCtx *de_ctx = NULL;
-    DetectModbus    *modbus = NULL;
+    StreamTcpInitConfig(TRUE);
 
     de_ctx = DetectEngineCtxInit();
     FAIL_IF_NULL(de_ctx);
 
     de_ctx->flags |= DE_QUIET;
+    s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
+                                           "(msg:\"Testing modbus code function\"; "
+                                           "modbus: access write; sid:1;)");
+    FAIL_IF_NULL(s);
 
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus.function\"; "
-                                       "modbus: function reserved;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
 
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+    FLOWLOCK_WRLOCK(&f);
+    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
+            writeSingleCoil, sizeof(writeSingleCoil));
+    FAIL_IF_NOT(r == 0);
+    FLOWLOCK_UNLOCK(&f);
 
-    FAIL_IF_NOT(modbus->category == MODBUS_CAT_RESERVED);
+    FAIL_IF_NULL(f.alstate);
 
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-    PASS;
-}
+    /* do detect */
+    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
 
-/** \test Signature containing a negative function category. */
-static int DetectModbusTest04(void)
-{
-    DetectEngineCtx *de_ctx = NULL;
-    DetectModbus    *modbus = NULL;
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
+    FAIL_IF_NOT(PacketAlertCheck(p, 1));
 
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus function\"; "
-                                       "modbus: function !assigned;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    FAIL_IF(modbus->category & MODBUS_CAT_PUBLIC_ASSIGNED);
-    FAIL_IF_NOT(modbus->category & MODBUS_CAT_PUBLIC_UNASSIGNED);
-    FAIL_IF_NOT(modbus->category & MODBUS_CAT_USER_DEFINED);
-    FAIL_IF_NOT(modbus->category & MODBUS_CAT_RESERVED);
-
-    DetectModbusCFree(modbus);
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineThreadCtxDeinit(&tv, det_ctx);
     SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
     DetectEngineCtxFree(de_ctx);
-    PASS;
-}
 
-/** \test Signature containing a access type. */
-static int DetectModbusTest05(void)
-{
-    DetectEngineCtx *de_ctx = NULL;
-    DetectModbus    *modbus = NULL;
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus.access\"; "
-                                       "modbus: access read;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    FAIL_IF_NOT(modbus->type == MODBUS_TYP_READ);
-
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
+    StreamTcpFreeConfig(TRUE);
+    FLOW_DESTROY(&f);
+    UTHFreePacket(p);
     PASS;
 }
 
-/** \test Signature containing a access function. */
-static int DetectModbusTest06(void)
+/** \test Signature containing a function. */
+static int DetectModbusTestFunction(void)
 {
+    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+    DetectEngineThreadCtx *det_ctx = NULL;
     DetectEngineCtx *de_ctx = NULL;
-    DetectModbus    *modbus = NULL;
-
-    uint8_t type = (MODBUS_TYP_READ | MODBUS_TYP_DISCRETES);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus.access\"; "
-                                       "modbus: access read discretes;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    FAIL_IF_NOT(modbus->type == type);
+    Flow f;
+    Packet *p = NULL;
+    Signature *s = NULL;
+    TcpSession ssn;
+    ThreadVars tv;
 
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-    PASS;
-}
-
-/** \test Signature containing a read access at an address. */
-static int DetectModbusTest07(void)
-{
-    DetectEngineCtx     *de_ctx = NULL;
-    DetectModbus        *modbus = NULL;
-    DetectModbusMode    mode = DETECT_MODBUS_EQ;
-
-    uint8_t type = MODBUS_TYP_READ;
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus.access\"; "
-                                       "modbus: access read, address 1000;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    FAIL_IF_NOT(modbus->type == type);
-    FAIL_IF_NOT((*modbus->address).mode == mode);
-    FAIL_IF_NOT((*modbus->address).min == 1000);
-
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-    PASS;
-}
-
-/** \test Signature containing a write access at a range of address. */
-static int DetectModbusTest08(void)
-{
-    DetectEngineCtx     *de_ctx = NULL;
-    DetectModbus        *modbus = NULL;
-    DetectModbusMode    mode = DETECT_MODBUS_GT;
-
-    uint8_t type = (MODBUS_TYP_WRITE | MODBUS_TYP_COILS);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus.access\"; "
-                                       "modbus: access write coils, address >500;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    FAIL_IF_NOT(modbus->type == type);
-    FAIL_IF_NOT((*modbus->address).mode == mode);
-    FAIL_IF_NOT((*modbus->address).min == 500);
-
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-    PASS;
-}
-
-/** \test Signature containing a write access at a address a range of value. */
-static int DetectModbusTest09(void)
-{
-    DetectEngineCtx     *de_ctx = NULL;
-    DetectModbus        *modbus = NULL;
-    DetectModbusMode    addressMode = DETECT_MODBUS_EQ;
-    DetectModbusMode    valueMode = DETECT_MODBUS_RA;
-
-    uint8_t type = (MODBUS_TYP_WRITE | MODBUS_TYP_HOLDING);
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus.access\"; "
-                                       "modbus: access write holding, address 100, value 500<>1000;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+    FAIL_IF_NULL(alp_tctx);
 
-    FAIL_IF_NOT(modbus->type == type);
-    FAIL_IF_NOT((*modbus->address).mode == addressMode);
-    FAIL_IF_NOT((*modbus->address).min == 100);
-    FAIL_IF_NOT((*modbus->data).mode == valueMode);
-    FAIL_IF_NOT((*modbus->data).min == 500);
-    FAIL_IF_NOT((*modbus->data).max == 1000);
+    memset(&tv, 0, sizeof(ThreadVars));
+    memset(&f, 0, sizeof(Flow));
+    memset(&ssn, 0, sizeof(TcpSession));
 
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-    PASS;
-}
-
-/** \test Signature containing a unit_id. */
-static int DetectModbusTest10(void)
-{
-    DetectEngineCtx    *de_ctx = NULL;
-    DetectModbus       *modbus = NULL;
-    DetectModbusMode    mode = DETECT_MODBUS_EQ;
+    p = UTHBuildPacket(writeSingleCoil, sizeof(writeSingleCoil), IPPROTO_TCP);
 
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus unit_id\"; "
-                                       "modbus: unit 10;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+    FLOW_INITIALIZE(&f);
+    f.alproto = ALPROTO_MODBUS;
+    f.protoctx = (void *)&ssn;
+    f.proto = IPPROTO_TCP;
+    f.flags |= FLOW_IPV4;
 
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+    p->flow = &f;
+    p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
+    p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
 
-    FAIL_IF_NOT((*modbus->unit_id).min == 10);
-    FAIL_IF_NOT((*modbus->unit_id).mode == mode);
-
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-    PASS;
-}
-
-/** \test Signature containing a unit_id, a function and a subfunction. */
-static int DetectModbusTest11(void)
-{
-    DetectEngineCtx    *de_ctx = NULL;
-    DetectModbus       *modbus = NULL;
-    DetectModbusMode    mode = DETECT_MODBUS_EQ;
+    StreamTcpInitConfig(TRUE);
 
     de_ctx = DetectEngineCtxInit();
     FAIL_IF_NULL(de_ctx);
 
     de_ctx->flags |= DE_QUIET;
+    s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
+                                           "(msg:\"Testing modbus code function\"; "
+                                           "modbus: function 8; sid:1;)");
+    FAIL_IF_NULL(s);
 
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus function and subfunction\"; "
-                                       "modbus: unit 10, function 8, subfunction 4;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    FAIL_IF_NOT((*modbus->unit_id).min == 10);
-    FAIL_IF_NOT((*modbus->unit_id).mode == mode);
-    FAIL_IF_NOT(modbus->function == 8);
-    FAIL_IF_NOT(modbus->subfunction == 4);
-
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
-    PASS;
-}
-
-/** \test Signature containing an unit_id and a read access at an address. */
-static int DetectModbusTest12(void)
-{
-    DetectEngineCtx     *de_ctx = NULL;
-    DetectModbus        *modbus = NULL;
-    DetectModbusMode    mode = DETECT_MODBUS_EQ;
-
-    uint8_t type = MODBUS_TYP_READ;
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
 
-    de_ctx->flags |= DE_QUIET;
+    FLOWLOCK_WRLOCK(&f);
+    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
+            restartCommOption, sizeof(restartCommOption));
+    FAIL_IF_NOT(r == 0);
+    FLOWLOCK_UNLOCK(&f);
 
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus.access\"; "
-                                       "modbus: unit 10, access read, address 1000;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+    FAIL_IF_NULL(f.alstate);
 
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
+    /* do detect */
+    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
 
-    FAIL_IF_NOT((*modbus->unit_id).min == 10);
-    FAIL_IF_NOT((*modbus->unit_id).mode == mode);
-    FAIL_IF_NOT(modbus->type == type);
-    FAIL_IF_NOT((*modbus->address).mode == mode);
-    FAIL_IF_NOT((*modbus->address).min == 1000);
+    FAIL_IF_NOT(PacketAlertCheck(p, 1));
 
-    DetectModbusCFree(modbus);
+    AppLayerParserThreadCtxFree(alp_tctx);
+    DetectEngineThreadCtxDeinit(&tv, det_ctx);
     SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
     DetectEngineCtxFree(de_ctx);
-    PASS;
-}
 
-/** \test Signature containing a range of unit_id. */
-static int DetectModbusTest13(void)
-{
-    DetectEngineCtx     *de_ctx = NULL;
-    DetectModbus        *modbus = NULL;
-    DetectModbusMode    mode = DETECT_MODBUS_RA;
-
-    de_ctx = DetectEngineCtxInit();
-    FAIL_IF_NULL(de_ctx);
-
-    de_ctx->flags |= DE_QUIET;
-
-    de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
-                                       "(msg:\"Testing modbus.access\"; "
-                                       "modbus: unit 10<>500;  sid:1;)");
-    FAIL_IF_NULL(de_ctx->sig_list);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
-    FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    modbus = DetectModbusRustToC(
-            (DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
-
-    FAIL_IF_NOT((*modbus->unit_id).min == 10);
-    FAIL_IF_NOT((*modbus->unit_id).max == 500);
-    FAIL_IF_NOT((*modbus->unit_id).mode == mode);
-
-    DetectModbusCFree(modbus);
-    SigGroupCleanup(de_ctx);
-    SigCleanSignatures(de_ctx);
-    DetectEngineCtxFree(de_ctx);
+    StreamTcpFreeConfig(TRUE);
+    FLOW_DESTROY(&f);
+    UTHFreePacket(p);
     PASS;
 }
 
@@ -674,31 +340,7 @@ static int DetectModbusTest13(void)
  */
 void DetectModbusRegisterTests(void)
 {
-    UtRegisterTest("DetectModbusTest01 - Testing function",
-                   DetectModbusTest01);
-    UtRegisterTest("DetectModbusTest02 - Testing function and subfunction",
-                   DetectModbusTest02);
-    UtRegisterTest("DetectModbusTest03 - Testing category function",
-                   DetectModbusTest03);
-    UtRegisterTest("DetectModbusTest04 - Testing category function in negative",
-                   DetectModbusTest04);
-    UtRegisterTest("DetectModbusTest05 - Testing access type",
-                   DetectModbusTest05);
-    UtRegisterTest("DetectModbusTest06 - Testing access function",
-                   DetectModbusTest06);
-    UtRegisterTest("DetectModbusTest07 - Testing access at address",
-                   DetectModbusTest07);
-    UtRegisterTest("DetectModbusTest08 - Testing a range of address",
-                   DetectModbusTest08);
-    UtRegisterTest("DetectModbusTest09 - Testing write a range of value",
-                   DetectModbusTest09);
-    UtRegisterTest("DetectModbusTest10 - Testing unit_id",
-                   DetectModbusTest10);
-    UtRegisterTest("DetectModbusTest11 - Testing unit_id, function and subfunction",
-                   DetectModbusTest11);
-    UtRegisterTest("DetectModbusTest12 - Testing unit_id and access at address",
-                   DetectModbusTest12);
-    UtRegisterTest("DetectModbusTest13 - Testing a range of unit_id",
-                   DetectModbusTest13);
+    UtRegisterTest("DetectModbusTestAccess", DetectModbusTestAccess);
+    UtRegisterTest("DetectModbusTestFunction", DetectModbusTestFunction);
 }
 #endif /* UNITTESTS */
index 2686e21f65330aaaa080e0b4094924e0d33ffc10..9c96ddeef8383f2b16e3cec89a5c118e1e44d6d5 100644 (file)
 #ifndef __DETECT_MODBUS_H__
 #define __DETECT_MODBUS_H__
 
-#include "app-layer-modbus.h"
-
-typedef enum {
-    DETECT_MODBUS_EQ = 0,   /** < EQual operator */
-    DETECT_MODBUS_LT,       /** < "Less Than" operator */
-    DETECT_MODBUS_GT,       /** < "Greater Than" operator */
-    DETECT_MODBUS_RA,       /** < RAnge operator */
-} DetectModbusMode;
-
-typedef struct DetectModbusValue_ {
-    uint16_t            min;    /** < Modbus minimum [range] or equal value to match */
-    uint16_t            max;    /** < Modbus maximum value [range] to match */
-    DetectModbusMode    mode;   /** < Modbus operator used in the address/data signature */
-} DetectModbusValue;
-
-typedef struct DetectModbus_ {
-    uint8_t             category;          /** < Modbus function code category to match */
-    uint8_t             function;          /** < Modbus function code to match */
-    uint16_t            subfunction;      /** < Modbus subfunction to match */
-    bool                has_subfunction;   /** < Modbus subfunction indicator */
-    uint8_t             type;              /** < Modbus access type to match */
-    DetectModbusValue   *unit_id;          /** < Modbus unit id to match */
-    DetectModbusValue   *address;          /** < Modbus address to match */
-    DetectModbusValue   *data;             /** < Modbus data to match */
-} DetectModbus;
-
 /* prototypes */
 void DetectModbusRegister(void);
 
index e6617c307f49361116a44131d951be0ce1b630d2..1ed21f4b23998d6827f904f62201f608f98eb492 100644 (file)
@@ -37,7 +37,6 @@
 #include "detect-engine-dcepayload.h"
 #include "detect-engine-state.h"
 #include "detect-engine-tag.h"
-#include "detect-engine-modbus.h"
 #include "detect-fast-pattern.h"
 #include "flow.h"
 #include "flow-timeout.h"
@@ -184,7 +183,6 @@ static void RegisterUnittests(void)
 #endif
     DeStateRegisterTests();
     MemcmpRegisterTests();
-    DetectEngineInspectModbusRegisterTests();
     DetectEngineRegisterTests();
     SCLogRegisterTests();
     MagicRegisterTests();