diff --git a/rust/Makefile.am b/rust/Makefile.am index 6939ffb53c..b003af914f 100644 --- a/rust/Makefile.am +++ b/rust/Makefile.am @@ -150,6 +150,7 @@ if HAVE_BINDGEN --allowlist-type 'AppLayerGetTxIterState' \ --allowlist-type 'AppLayerStateData' \ --allowlist-type 'AppLayerGetTxIterTuple' \ + --allowlist-type 'AppLayerResult' \ --allowlist-type 'StreamSlice' \ --allowlist-function 'SC.*' \ --allowlist-var 'SC.*' \ diff --git a/rust/src/applayer.rs b/rust/src/applayer.rs index fbe489037c..ce1805243b 100644 --- a/rust/src/applayer.rs +++ b/rust/src/applayer.rs @@ -33,7 +33,8 @@ use suricata_sys::sys::{ }; pub use suricata_sys::sys::{ - AppLayerGetFileState, AppLayerStateData, AppLayerGetTxIterTuple, StreamSlice, + AppLayerGetFileState, AppLayerGetTxIterTuple, AppLayerResult, AppLayerStateData, + StreamSlice, }; #[cfg(not(test))] @@ -317,33 +318,35 @@ macro_rules!export_state_data_get { } } -#[repr(C)] -#[derive(Default,Debug,PartialEq, Eq,Copy,Clone)] -pub struct AppLayerResult { - pub status: i32, - pub consumed: u32, - pub needed: u32, +pub trait AppLayerResultRust { + fn ok() -> Self; + fn err() -> Self; + fn incomplete(consumed: u32, needed: u32) -> Self; + fn is_ok(&self) -> bool; + fn is_err(&self) -> bool; + fn is_incomplete(&self) -> bool; } -impl AppLayerResult { +impl AppLayerResultRust for AppLayerResult { /// parser has successfully processed in the input, and has consumed all of it - pub fn ok() -> Self { + fn ok() -> Self { Default::default() } /// parser has hit an unrecoverable error. Returning this to the API /// leads to no further calls to the parser. - pub fn err() -> Self { - return Self { + fn err() -> Self { + return AppLayerResult{ status: -1, ..Default::default() }; } + /// parser needs more data. Through 'consumed' it will indicate how many /// of the input bytes it has consumed. Through 'needed' it will indicate /// how many more bytes it needs before getting called again. /// Note: consumed should never be more than the input len /// needed + consumed should be more than the input len - pub fn incomplete(consumed: u32, needed: u32) -> Self { + fn incomplete(consumed: u32, needed: u32) -> Self { return Self { status: 1, consumed, @@ -351,39 +354,19 @@ impl AppLayerResult { }; } - pub fn is_ok(self) -> bool { + fn is_ok(&self) -> bool { self.status == 0 } - pub fn is_err(self) -> bool { + fn is_err(&self) -> bool { self.status == -1 } - pub fn is_incomplete(self) -> bool { + fn is_incomplete(&self) -> bool { self.status == 1 } } -impl From for AppLayerResult { - fn from(v: bool) -> Self { - if !v { - Self::err() - } else { - Self::ok() - } - } -} - -impl From for AppLayerResult { - fn from(v: i32) -> Self { - if v < 0 { - Self::err() - } else { - Self::ok() - } - } -} - /// Rust parser declaration #[repr(C)] pub struct RustParser { diff --git a/rust/src/bittorrent_dht/bittorrent_dht.rs b/rust/src/bittorrent_dht/bittorrent_dht.rs index 0d3e6c02bd..6ada765e1d 100644 --- a/rust/src/bittorrent_dht/bittorrent_dht.rs +++ b/rust/src/bittorrent_dht/bittorrent_dht.rs @@ -106,15 +106,15 @@ impl BitTorrentDHTState { } } - pub fn parse(&mut self, input: &[u8], _direction: Direction) -> bool { + pub fn parse(&mut self, input: &[u8], _direction: Direction) -> AppLayerResult { if !Self::is_dht(input) { - return true; + return AppLayerResult::ok(); } let mut tx = self.new_tx(_direction); - let mut status = true; + let mut status = AppLayerResult::ok(); if let Err(_e) = parse_bittorrent_dht_packet(input, &mut tx) { - status = false; + status = AppLayerResult::err(); tx.set_event(BitTorrentDHTEvent::MalformedPacket); SCLogDebug!("BitTorrent DHT Parsing Error: {}", _e); } @@ -181,7 +181,7 @@ unsafe extern "C" fn parse( ) -> AppLayerResult { let state = cast_pointer!(state, BitTorrentDHTState); let buf = stream_slice.as_slice(); - state.parse(buf, direction).into() + state.parse(buf, direction) } unsafe extern "C" fn state_get_tx( diff --git a/rust/src/dcerpc/dcerpc.rs b/rust/src/dcerpc/dcerpc.rs index 18347fb99f..139f0415cd 100644 --- a/rust/src/dcerpc/dcerpc.rs +++ b/rust/src/dcerpc/dcerpc.rs @@ -1227,7 +1227,7 @@ pub unsafe extern "C" fn SCRegisterDcerpcParser() { #[cfg(test)] mod tests { - use crate::applayer::{AppLayerResult, StreamSlice, StreamSliceRust}; + use crate::applayer::{AppLayerResult, AppLayerResultRust, StreamSlice, StreamSliceRust}; use crate::core::*; use crate::dcerpc::dcerpc::DCERPCState; use crate::direction::Direction; diff --git a/rust/src/dcerpc/dcerpc_udp.rs b/rust/src/dcerpc/dcerpc_udp.rs index d90a934119..5d71159fa6 100644 --- a/rust/src/dcerpc/dcerpc_udp.rs +++ b/rust/src/dcerpc/dcerpc_udp.rs @@ -410,7 +410,7 @@ pub unsafe extern "C" fn SCRegisterDcerpcUdpParser() { #[cfg(test)] mod tests { - use crate::applayer::AppLayerResult; + use crate::applayer::{AppLayerResult, AppLayerResultRust}; use crate::dcerpc::dcerpc_udp::DCERPCUDPState; use crate::dcerpc::parser; diff --git a/rust/src/sip/sip.rs b/rust/src/sip/sip.rs index 6b834117a3..520ddabae1 100755 --- a/rust/src/sip/sip.rs +++ b/rust/src/sip/sip.rs @@ -122,7 +122,7 @@ impl SIPState { } // app-layer-frame-documentation tag start: parse_request - fn parse_request(&mut self, flow: *mut Flow, stream_slice: StreamSlice) -> bool { + fn parse_request(&mut self, flow: *mut Flow, stream_slice: StreamSlice) -> AppLayerResult { let input = stream_slice.as_slice(); let _pdu = Frame::new( flow, @@ -143,16 +143,16 @@ impl SIPState { tx.request_line = req_line; } self.transactions.push_back(tx); - return true; + return AppLayerResult::ok(); } // app-layer-frame-documentation tag end: parse_request Err(Err::Incomplete(_)) => { self.set_event(SIPEvent::IncompleteData); - return false; + return AppLayerResult::err(); } Err(_) => { self.set_event(SIPEvent::InvalidData); - return false; + return AppLayerResult::err(); } } } @@ -222,7 +222,7 @@ impl SIPState { return AppLayerResult::ok(); } - fn parse_response(&mut self, flow: *mut Flow, stream_slice: StreamSlice) -> bool { + fn parse_response(&mut self, flow: *mut Flow, stream_slice: StreamSlice) -> AppLayerResult { let input = stream_slice.as_slice(); let _pdu = Frame::new( flow, @@ -243,15 +243,15 @@ impl SIPState { tx.response_line = resp_line; } self.transactions.push_back(tx); - return true; + return AppLayerResult::ok(); } Err(Err::Incomplete(_)) => { self.set_event(SIPEvent::IncompleteData); - return false; + return AppLayerResult::err(); } Err(_) => { self.set_event(SIPEvent::InvalidData); - return false; + return AppLayerResult::err(); } } } @@ -453,7 +453,7 @@ unsafe extern "C" fn sip_parse_request( stream_slice: StreamSlice, _data: *mut std::os::raw::c_void, ) -> AppLayerResult { let state = cast_pointer!(state, SIPState); - state.parse_request(flow, stream_slice).into() + state.parse_request(flow, stream_slice) } unsafe extern "C" fn sip_parse_request_tcp( @@ -477,7 +477,7 @@ unsafe extern "C" fn sip_parse_response( stream_slice: StreamSlice, _data: *mut std::os::raw::c_void, ) -> AppLayerResult { let state = cast_pointer!(state, SIPState); - state.parse_response(flow, stream_slice).into() + state.parse_response(flow, stream_slice) } unsafe extern "C" fn sip_parse_response_tcp( diff --git a/rust/src/snmp/snmp.rs b/rust/src/snmp/snmp.rs index 5e83125acc..0064997b43 100644 --- a/rust/src/snmp/snmp.rs +++ b/rust/src/snmp/snmp.rs @@ -162,7 +162,7 @@ impl<'a> SNMPState<'a> { tx.info = Some(pdu_info); } - fn handle_snmp_v12(&mut self, msg: SnmpMessage<'a>, _direction: Direction) -> i32 { + fn handle_snmp_v12(&mut self, msg: SnmpMessage<'a>, _direction: Direction) -> AppLayerResult { let mut tx = self.new_tx(_direction); // in the message, version is encoded as 0 (version 1) or 1 (version 2) if self.version != msg.version + 1 { @@ -172,10 +172,10 @@ impl<'a> SNMPState<'a> { self.add_pdu_info(&msg.pdu, &mut tx); tx.community = Some(msg.community); self.transactions.push(tx); - 0 + AppLayerResult::ok() } - fn handle_snmp_v3(&mut self, msg: SnmpV3Message<'a>, _direction: Direction) -> i32 { + fn handle_snmp_v3(&mut self, msg: SnmpV3Message<'a>, _direction: Direction) -> AppLayerResult { let mut tx = self.new_tx(_direction); if self.version != msg.version { SCLogDebug!("SNMP version mismatch: expected {}, received {}", self.version, msg.version); @@ -198,13 +198,13 @@ impl<'a> SNMPState<'a> { } } self.transactions.push(tx); - 0 + AppLayerResult::ok() } /// Parse an SNMP request message /// /// Returns 0 if successful, or -1 on error - fn parse(&mut self, i: &'a [u8], direction: Direction) -> i32 { + fn parse(&mut self, i: &'a [u8], direction: Direction) -> AppLayerResult { if self.version == 0 { if let Ok((_, x)) = parse_pdu_envelope_version(i) { self.version = x; @@ -217,7 +217,7 @@ impl<'a> SNMPState<'a> { Err(_e) => { SCLogDebug!("parse_snmp failed: {:?}", _e); self.set_event(SNMPEvent::MalformedData); - -1 + AppLayerResult::err() }, } } @@ -293,7 +293,7 @@ unsafe extern "C" fn snmp_parse_request(_flow: *mut Flow, _data: *mut std::os::raw::c_void, ) -> AppLayerResult { let state = cast_pointer!(state,SNMPState); - state.parse(stream_slice.as_slice(), Direction::ToServer).into() + state.parse(stream_slice.as_slice(), Direction::ToServer) } unsafe extern "C" fn snmp_parse_response(_flow: *mut Flow, @@ -303,7 +303,7 @@ unsafe extern "C" fn snmp_parse_response(_flow: *mut Flow, _data: *mut std::os::raw::c_void, ) -> AppLayerResult { let state = cast_pointer!(state,SNMPState); - state.parse(stream_slice.as_slice(), Direction::ToClient).into() + state.parse(stream_slice.as_slice(), Direction::ToClient) } unsafe extern "C" fn snmp_state_get_tx(state: *mut std::os::raw::c_void, diff --git a/rust/sys/src/sys.rs b/rust/sys/src/sys.rs index a43254ac18..02c905b95a 100644 --- a/rust/sys/src/sys.rs +++ b/rust/sys/src/sys.rs @@ -1073,6 +1073,13 @@ impl Default for StreamSlice { } } } +#[repr(C)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] +pub struct AppLayerResult { + pub status: i32, + pub consumed: u32, + pub needed: u32, +} extern "C" { pub fn SCAppLayerParserReallocCtx(alproto: AppProto) -> ::std::os::raw::c_int; } diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 62c1f5625e..2b35daa2eb 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -165,6 +165,12 @@ static inline uint32_t StreamSliceGetDataLen(const StreamSlice *stream_slice) return stream_slice->input_len; } +typedef struct AppLayerResult { + int32_t status; + uint32_t consumed; + uint32_t needed; +} AppLayerResult; + /** \brief tx iterator prototype */ typedef AppLayerGetTxIterTuple (*AppLayerGetTxIteratorFunc) (const uint8_t ipproto, const AppProto alproto,