]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/enip: convert to nom 8
authorJason Ish <jason.ish@oisf.net>
Mon, 27 Oct 2025 21:59:47 +0000 (15:59 -0600)
committerJason Ish <jason.ish@oisf.net>
Thu, 30 Oct 2025 15:15:41 +0000 (09:15 -0600)
Ticket: #8038

rust/src/enip/enip.rs
rust/src/enip/parser.rs

index 38aefbf37819016bbcdd138fbdbe48c87ee771f7..c9a61a516759624fe243f79d53af1f1e2a2aaa4f 100644 (file)
@@ -24,7 +24,7 @@ use crate::detect::EnumString;
 use crate::direction::Direction;
 use crate::flow::Flow;
 use crate::frames::Frame;
-use nom7 as nom;
+use nom8 as nom;
 use std;
 use std::collections::VecDeque;
 use std::ffi::CString;
index fec12ba66a1350fb0e20d38e4dfd25703bf132ee..668e14fed48c38a37c6ff1b490ed966a554a5983 100644 (file)
  * 02110-1301, USA.
  */
 
-use nom7::bytes::streaming::take;
-use nom7::error::{make_error, ErrorKind};
-use nom7::multi::count;
-use nom7::number::streaming::{le_u16, le_u32, le_u64, le_u8};
-use nom7::IResult;
+use nom8::bytes::complete::take;
+use nom8::error::{make_error, ErrorKind};
+use nom8::multi::count;
+use nom8::number::complete::{le_u16, le_u32, le_u64, le_u8};
+use nom8::IResult;
+use nom8::Parser;
 
 use super::constant::EnipCommand;
 use crate::detect::EnumString;
@@ -35,12 +36,12 @@ pub struct EnipHeader {
 }
 
 pub fn parse_enip_header(i: &[u8]) -> IResult<&[u8], EnipHeader> {
-    let (i, cmd) = le_u16(i)?;
-    let (i, pdulen) = le_u16(i)?;
-    let (i, session) = le_u32(i)?;
-    let (i, status) = le_u32(i)?;
-    let (i, context) = le_u64(i)?;
-    let (i, options) = le_u32(i)?;
+    let (i, cmd) = le_u16.parse(i)?;
+    let (i, pdulen) = le_u16.parse(i)?;
+    let (i, session) = le_u32.parse(i)?;
+    let (i, status) = le_u32.parse(i)?;
+    let (i, context) = le_u64.parse(i)?;
+    let (i, options) = le_u32.parse(i)?;
     Ok((
         i,
         EnipHeader {
@@ -55,8 +56,8 @@ pub fn parse_enip_header(i: &[u8]) -> IResult<&[u8], EnipHeader> {
 }
 
 pub fn parse_enip_list_interfaces(i: &[u8]) -> IResult<&[u8], Vec<u16>> {
-    let (i, nb) = le_u16(i)?;
-    let (i, r) = count(le_u16, nb.into())(i)?;
+    let (i, nb) = le_u16.parse(i)?;
+    let (i, r) = count(le_u16, nb.into()).parse(i)?;
     Ok((i, r))
 }
 
@@ -154,27 +155,27 @@ pub fn cip_segment_type_string(p: u8) -> Option<&'static str> {
 }
 
 pub fn parse_cip_path_segment(i: &[u8]) -> IResult<&[u8], EnipCipPathSegment> {
-    let (i, segment_type) = le_u8(i)?;
+    let (i, segment_type) = le_u8.parse(i)?;
     if segment_type >> 5 != 1 {
         // we only handle logical segment
-        return Err(nom7::Err::Error(make_error(i, ErrorKind::Verify)));
+        return Err(nom8::Err::Error(make_error(i, ErrorKind::Verify)));
     }
     let (i, value) = match segment_type & 3 {
         0 => {
-            let (i, v) = le_u8(i)?;
+            let (i, v) = le_u8.parse(i)?;
             Ok((i, v as u32))
         }
         1 => {
-            let (i, _pad) = le_u8(i)?;
-            let (i, v) = le_u16(i)?;
+            let (i, _pad) = le_u8.parse(i)?;
+            let (i, v) = le_u16.parse(i)?;
             Ok((i, v as u32))
         }
         2 => {
-            let (i, _pad) = le_u8(i)?;
-            le_u32(i)
+            let (i, _pad) = le_u8.parse(i)?;
+            le_u32.parse(i)
         }
         // There may be more cases to handle
-        _ => Err(nom7::Err::Error(make_error(i, ErrorKind::Switch))),
+        _ => Err(nom8::Err::Error(make_error(i, ErrorKind::Switch))),
     }?;
     return Ok((
         i,
@@ -186,8 +187,8 @@ pub fn parse_cip_path_segment(i: &[u8]) -> IResult<&[u8], EnipCipPathSegment> {
 }
 
 pub fn parse_cip_path(i: &[u8]) -> IResult<&[u8], (Vec<EnipCipPathSegment>, usize)> {
-    let (i, nb) = le_u8(i)?;
-    let (i, data) = take(2 * (nb as usize))(i)?;
+    let (i, nb) = le_u8.parse(i)?;
+    let (i, data) = take(2 * (nb as usize)).parse(i)?;
     let consumed = 1 + 2 * (nb as usize);
     let mut rem = data;
     let mut segments = Vec::new();
@@ -204,15 +205,15 @@ pub const CIP_SET_ATTR_LIST: u8 = 4;
 pub const CIP_MULTIPLE_SERVICE: u8 = 0xa;
 
 pub fn parse_cip_request_get_attr_list(i: &[u8]) -> IResult<&[u8], EnipCipRequestGetAttributeList> {
-    let (i, nb) = le_u16(i)?;
-    let (i, attr_list) = count(le_u16, nb.into())(i)?;
+    let (i, nb) = le_u16.parse(i)?;
+    let (i, attr_list) = count(le_u16, nb.into()).parse(i)?;
     Ok((i, EnipCipRequestGetAttributeList { attr_list }))
 }
 
 pub fn parse_cip_request_set_attr_list(i: &[u8]) -> IResult<&[u8], EnipCipRequestSetAttributeList> {
-    let (i, nb) = le_u16(i)?;
+    let (i, nb) = le_u16.parse(i)?;
     if nb > 0 {
-        let (i, first_attr) = le_u16(i)?;
+        let (i, first_attr) = le_u16.parse(i)?;
         // do not parse further because attribute data is class specific
         return Ok((
             i,
@@ -228,8 +229,8 @@ pub fn parse_cip_reqresp_multiple(
     i: &[u8], offset_from_cip: usize,
 ) -> IResult<&[u8], EnipCipReqRespMultipleService> {
     let start = i;
-    let (i, nb) = le_u16(i)?;
-    let (i, offset_list) = count(le_u16, nb.into())(i)?;
+    let (i, nb) = le_u16.parse(i)?;
+    let (i, offset_list) = count(le_u16, nb.into()).parse(i)?;
     let mut packet_list = Vec::new();
     let mut size_list = Vec::new();
     let mut rem = i;
@@ -240,7 +241,7 @@ pub fn parse_cip_reqresp_multiple(
             size_list.push(start[offset_list[j] as usize..].len() - rem2.len());
             rem = rem2;
         } else {
-            return Err(nom7::Err::Error(make_error(i, ErrorKind::LengthValue)));
+            return Err(nom8::Err::Error(make_error(i, ErrorKind::LengthValue)));
         }
     }
     Ok((
@@ -276,10 +277,10 @@ pub fn parse_cip_request(i: &[u8], service: u8, multi: bool) -> IResult<&[u8], E
 }
 
 pub fn parse_cip_response(i: &[u8], service: u8, multi: bool) -> IResult<&[u8], EnipCipResponse> {
-    let (i, _reserved) = le_u8(i)?;
-    let (i, status) = le_u8(i)?;
-    let (i, status_ext_nb) = le_u8(i)?;
-    let (i, status_extended) = take(status_ext_nb as usize)(i)?;
+    let (i, _reserved) = le_u8.parse(i)?;
+    let (i, status) = le_u8.parse(i)?;
+    let (i, status_ext_nb) = le_u8.parse(i)?;
+    let (i, status_extended) = take(status_ext_nb as usize).parse(i)?;
     let offset_from_cip = 4 + (status_ext_nb as usize);
     let (i, payload) = match service {
         // CIP_GET_ATTR_LIST : need to parse attribute value variant, based on cip class
@@ -310,7 +311,7 @@ pub fn parse_cip_multi(i: &[u8]) -> IResult<&[u8], CipData> {
 }
 
 pub fn parse_cip(i: &[u8], multi: bool) -> IResult<&[u8], CipData> {
-    let (i, service) = le_u8(i)?;
+    let (i, service) = le_u8.parse(i)?;
     let (i, cipdir) = if service & 0x80 == 0 {
         let (i, req) = parse_cip_request(i, service, multi)?;
         Ok((i, CipDir::Request(req)))
@@ -371,18 +372,18 @@ pub const ENIP_ITEM_TYPE_IDENTITY: u16 = 0xc;
 pub const ENIP_ITEM_TYPE_SERVICES: u16 = 0x100;
 
 pub fn parse_cip_identity(i: &[u8]) -> IResult<&[u8], EnipItemIdentity> {
-    let (i, protocol_version) = le_u16(i)?;
-    let (i, _sock_addr) = take(16_usize)(i)?;
-    let (i, vendor_id) = le_u16(i)?;
-    let (i, device_type) = le_u16(i)?;
-    let (i, product_code) = le_u16(i)?;
-    let (i, revision_major) = le_u8(i)?;
-    let (i, revision_minor) = le_u8(i)?;
-    let (i, status) = le_u16(i)?;
-    let (i, serial) = le_u32(i)?;
-    let (i, prod_name_len) = le_u8(i)?;
-    let (i, product_name) = take(prod_name_len as usize)(i)?;
-    let (i, state) = le_u8(i)?;
+    let (i, protocol_version) = le_u16.parse(i)?;
+    let (i, _sock_addr) = take(16_usize).parse(i)?;
+    let (i, vendor_id) = le_u16.parse(i)?;
+    let (i, device_type) = le_u16.parse(i)?;
+    let (i, product_code) = le_u16.parse(i)?;
+    let (i, revision_major) = le_u8.parse(i)?;
+    let (i, revision_minor) = le_u8.parse(i)?;
+    let (i, status) = le_u16.parse(i)?;
+    let (i, serial) = le_u32.parse(i)?;
+    let (i, prod_name_len) = le_u8.parse(i)?;
+    let (i, product_name) = take(prod_name_len as usize).parse(i)?;
+    let (i, state) = le_u8.parse(i)?;
 
     return Ok((
         i,
@@ -409,9 +410,9 @@ pub struct EnipItemServices {
 }
 
 pub fn parse_enip_services(i: &[u8]) -> IResult<&[u8], EnipItemServices> {
-    let (i, protocol_version) = le_u16(i)?;
-    let (i, capabilities) = le_u16(i)?;
-    let (i, service_name) = take(16_usize)(i)?;
+    let (i, protocol_version) = le_u16.parse(i)?;
+    let (i, capabilities) = le_u16.parse(i)?;
+    let (i, service_name) = take(16_usize).parse(i)?;
     return Ok((
         i,
         EnipItemServices {
@@ -423,10 +424,10 @@ pub fn parse_enip_services(i: &[u8]) -> IResult<&[u8], EnipItemServices> {
 }
 
 pub fn parse_enip_cip_item(i: &[u8], start: usize) -> IResult<&[u8], EnipCipItem> {
-    let (i, item_type) = le_u16(i)?;
-    let (i, item_length) = le_u16(i)?;
+    let (i, item_type) = le_u16.parse(i)?;
+    let (i, item_length) = le_u16.parse(i)?;
     let mut cip_offset = start + 4;
-    let (i, data) = take(item_length as usize)(i)?;
+    let (i, data) = take(item_length as usize).parse(i)?;
     let (_, payload) = match item_type {
         ENIP_ITEM_TYPE_IDENTITY => {
             let (_, li) = parse_cip_identity(data)?;
@@ -437,7 +438,7 @@ pub fn parse_enip_cip_item(i: &[u8], start: usize) -> IResult<&[u8], EnipCipItem
             Ok((data, EnipItemPayload::Services(ls)))
         }
         ENIP_ITEM_TYPE_CONNECTED_DATA => {
-            let (data, seq_num) = le_u16(data)?;
+            let (data, seq_num) = le_u16.parse(data)?;
             cip_offset += 2;
             let (_, cip) = parse_cip_base(data)?;
             Ok((
@@ -477,7 +478,7 @@ pub struct EnipCIP {
 }
 
 pub fn parse_enip_cip_items(i: &[u8]) -> IResult<&[u8], Vec<EnipCipItem>> {
-    let (i, nb) = le_u16(i)?;
+    let (i, nb) = le_u16.parse(i)?;
     let mut start = 26; // ENIP_HEADER_LEN + fields parsed
     let mut items = Vec::new();
     let mut rem = i;
@@ -491,9 +492,9 @@ pub fn parse_enip_cip_items(i: &[u8]) -> IResult<&[u8], Vec<EnipCipItem>> {
 }
 
 pub fn parse_enip_cip(i: &[u8]) -> IResult<&[u8], EnipCIP> {
-    let (i, handle) = le_u32(i)?;
-    let (i, timeout) = le_u16(i)?;
-    let (i, nb) = le_u16(i)?;
+    let (i, handle) = le_u32.parse(i)?;
+    let (i, timeout) = le_u16.parse(i)?;
+    let (i, nb) = le_u16.parse(i)?;
     let mut start = 32; // ENIP_HEADER_LEN + fields parsed
     let mut items = Vec::new();
     let mut rem = i;
@@ -514,8 +515,8 @@ pub fn parse_enip_cip(i: &[u8]) -> IResult<&[u8], EnipCIP> {
 }
 
 pub fn parse_enip_register_session(i: &[u8]) -> IResult<&[u8], EnipRegisterSession> {
-    let (i, protocol_version) = le_u16(i)?;
-    let (i, options) = le_u16(i)?;
+    let (i, protocol_version) = le_u16.parse(i)?;
+    let (i, options) = le_u16.parse(i)?;
     Ok((
         i,
         EnipRegisterSession {
@@ -534,7 +535,7 @@ pub struct EnipPdu {
 
 pub fn parse_enip_pdu(i: &[u8]) -> IResult<&[u8], EnipPdu> {
     let (i, header) = parse_enip_header(i)?;
-    let (i, data) = take(header.pdulen as usize)(i)?;
+    let (i, data) = take(header.pdulen as usize).parse(i)?;
     let mut invalid = false;
     match EnipCommand::from_u(header.cmd) {
         Some(EnipCommand::RegisterSession) => {