rust: move AppLayerResult definition to C

and bindgen it to rust

Will make easier the bindgen of RustParser structure which uses
a callback which uses AppLayerResult

Keep From<> impl in sys crate that defines it
pull/14758/head
Philippe Antoine 7 months ago committed by Victor Julien
parent 06f78b2a22
commit 8eaced3c1e

@ -150,6 +150,7 @@ if HAVE_BINDGEN
--allowlist-type 'AppLayerGetTxIterState' \ --allowlist-type 'AppLayerGetTxIterState' \
--allowlist-type 'AppLayerStateData' \ --allowlist-type 'AppLayerStateData' \
--allowlist-type 'AppLayerGetTxIterTuple' \ --allowlist-type 'AppLayerGetTxIterTuple' \
--allowlist-type 'AppLayerResult' \
--allowlist-type 'StreamSlice' \ --allowlist-type 'StreamSlice' \
--allowlist-function 'SC.*' \ --allowlist-function 'SC.*' \
--allowlist-var 'SC.*' \ --allowlist-var 'SC.*' \

@ -33,7 +33,8 @@ use suricata_sys::sys::{
}; };
pub use suricata_sys::sys::{ pub use suricata_sys::sys::{
AppLayerGetFileState, AppLayerStateData, AppLayerGetTxIterTuple, StreamSlice, AppLayerGetFileState, AppLayerGetTxIterTuple, AppLayerResult, AppLayerStateData,
StreamSlice,
}; };
#[cfg(not(test))] #[cfg(not(test))]
@ -317,33 +318,35 @@ macro_rules!export_state_data_get {
} }
} }
#[repr(C)] pub trait AppLayerResultRust {
#[derive(Default,Debug,PartialEq, Eq,Copy,Clone)] fn ok() -> Self;
pub struct AppLayerResult { fn err() -> Self;
pub status: i32, fn incomplete(consumed: u32, needed: u32) -> Self;
pub consumed: u32, fn is_ok(&self) -> bool;
pub needed: u32, 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 /// parser has successfully processed in the input, and has consumed all of it
pub fn ok() -> Self { fn ok() -> Self {
Default::default() Default::default()
} }
/// parser has hit an unrecoverable error. Returning this to the API /// parser has hit an unrecoverable error. Returning this to the API
/// leads to no further calls to the parser. /// leads to no further calls to the parser.
pub fn err() -> Self { fn err() -> Self {
return Self { return AppLayerResult{
status: -1, status: -1,
..Default::default() ..Default::default()
}; };
} }
/// parser needs more data. Through 'consumed' it will indicate how many /// parser needs more data. Through 'consumed' it will indicate how many
/// of the input bytes it has consumed. Through 'needed' it will indicate /// of the input bytes it has consumed. Through 'needed' it will indicate
/// how many more bytes it needs before getting called again. /// how many more bytes it needs before getting called again.
/// Note: consumed should never be more than the input len /// Note: consumed should never be more than the input len
/// needed + consumed should 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 { return Self {
status: 1, status: 1,
consumed, consumed,
@ -351,39 +354,19 @@ impl AppLayerResult {
}; };
} }
pub fn is_ok(self) -> bool { fn is_ok(&self) -> bool {
self.status == 0 self.status == 0
} }
pub fn is_err(self) -> bool { fn is_err(&self) -> bool {
self.status == -1 self.status == -1
} }
pub fn is_incomplete(self) -> bool { fn is_incomplete(&self) -> bool {
self.status == 1 self.status == 1
} }
} }
impl From<bool> for AppLayerResult {
fn from(v: bool) -> Self {
if !v {
Self::err()
} else {
Self::ok()
}
}
}
impl From<i32> for AppLayerResult {
fn from(v: i32) -> Self {
if v < 0 {
Self::err()
} else {
Self::ok()
}
}
}
/// Rust parser declaration /// Rust parser declaration
#[repr(C)] #[repr(C)]
pub struct RustParser { pub struct RustParser {

@ -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) { if !Self::is_dht(input) {
return true; return AppLayerResult::ok();
} }
let mut tx = self.new_tx(_direction); 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) { if let Err(_e) = parse_bittorrent_dht_packet(input, &mut tx) {
status = false; status = AppLayerResult::err();
tx.set_event(BitTorrentDHTEvent::MalformedPacket); tx.set_event(BitTorrentDHTEvent::MalformedPacket);
SCLogDebug!("BitTorrent DHT Parsing Error: {}", _e); SCLogDebug!("BitTorrent DHT Parsing Error: {}", _e);
} }
@ -181,7 +181,7 @@ unsafe extern "C" fn parse(
) -> AppLayerResult { ) -> AppLayerResult {
let state = cast_pointer!(state, BitTorrentDHTState); let state = cast_pointer!(state, BitTorrentDHTState);
let buf = stream_slice.as_slice(); let buf = stream_slice.as_slice();
state.parse(buf, direction).into() state.parse(buf, direction)
} }
unsafe extern "C" fn state_get_tx( unsafe extern "C" fn state_get_tx(

@ -1227,7 +1227,7 @@ pub unsafe extern "C" fn SCRegisterDcerpcParser() {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::applayer::{AppLayerResult, StreamSlice, StreamSliceRust}; use crate::applayer::{AppLayerResult, AppLayerResultRust, StreamSlice, StreamSliceRust};
use crate::core::*; use crate::core::*;
use crate::dcerpc::dcerpc::DCERPCState; use crate::dcerpc::dcerpc::DCERPCState;
use crate::direction::Direction; use crate::direction::Direction;

@ -410,7 +410,7 @@ pub unsafe extern "C" fn SCRegisterDcerpcUdpParser() {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::applayer::AppLayerResult; use crate::applayer::{AppLayerResult, AppLayerResultRust};
use crate::dcerpc::dcerpc_udp::DCERPCUDPState; use crate::dcerpc::dcerpc_udp::DCERPCUDPState;
use crate::dcerpc::parser; use crate::dcerpc::parser;

@ -122,7 +122,7 @@ impl SIPState {
} }
// app-layer-frame-documentation tag start: parse_request // 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 input = stream_slice.as_slice();
let _pdu = Frame::new( let _pdu = Frame::new(
flow, flow,
@ -143,16 +143,16 @@ impl SIPState {
tx.request_line = req_line; tx.request_line = req_line;
} }
self.transactions.push_back(tx); self.transactions.push_back(tx);
return true; return AppLayerResult::ok();
} }
// app-layer-frame-documentation tag end: parse_request // app-layer-frame-documentation tag end: parse_request
Err(Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
self.set_event(SIPEvent::IncompleteData); self.set_event(SIPEvent::IncompleteData);
return false; return AppLayerResult::err();
} }
Err(_) => { Err(_) => {
self.set_event(SIPEvent::InvalidData); self.set_event(SIPEvent::InvalidData);
return false; return AppLayerResult::err();
} }
} }
} }
@ -222,7 +222,7 @@ impl SIPState {
return AppLayerResult::ok(); 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 input = stream_slice.as_slice();
let _pdu = Frame::new( let _pdu = Frame::new(
flow, flow,
@ -243,15 +243,15 @@ impl SIPState {
tx.response_line = resp_line; tx.response_line = resp_line;
} }
self.transactions.push_back(tx); self.transactions.push_back(tx);
return true; return AppLayerResult::ok();
} }
Err(Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
self.set_event(SIPEvent::IncompleteData); self.set_event(SIPEvent::IncompleteData);
return false; return AppLayerResult::err();
} }
Err(_) => { Err(_) => {
self.set_event(SIPEvent::InvalidData); 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, stream_slice: StreamSlice, _data: *mut std::os::raw::c_void,
) -> AppLayerResult { ) -> AppLayerResult {
let state = cast_pointer!(state, SIPState); 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( 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, stream_slice: StreamSlice, _data: *mut std::os::raw::c_void,
) -> AppLayerResult { ) -> AppLayerResult {
let state = cast_pointer!(state, SIPState); 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( unsafe extern "C" fn sip_parse_response_tcp(

@ -162,7 +162,7 @@ impl<'a> SNMPState<'a> {
tx.info = Some(pdu_info); 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); let mut tx = self.new_tx(_direction);
// in the message, version is encoded as 0 (version 1) or 1 (version 2) // in the message, version is encoded as 0 (version 1) or 1 (version 2)
if self.version != msg.version + 1 { if self.version != msg.version + 1 {
@ -172,10 +172,10 @@ impl<'a> SNMPState<'a> {
self.add_pdu_info(&msg.pdu, &mut tx); self.add_pdu_info(&msg.pdu, &mut tx);
tx.community = Some(msg.community); tx.community = Some(msg.community);
self.transactions.push(tx); 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); let mut tx = self.new_tx(_direction);
if self.version != msg.version { if self.version != msg.version {
SCLogDebug!("SNMP version mismatch: expected {}, received {}", 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); self.transactions.push(tx);
0 AppLayerResult::ok()
} }
/// Parse an SNMP request message /// Parse an SNMP request message
/// ///
/// Returns 0 if successful, or -1 on error /// 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 self.version == 0 {
if let Ok((_, x)) = parse_pdu_envelope_version(i) { if let Ok((_, x)) = parse_pdu_envelope_version(i) {
self.version = x; self.version = x;
@ -217,7 +217,7 @@ impl<'a> SNMPState<'a> {
Err(_e) => { Err(_e) => {
SCLogDebug!("parse_snmp failed: {:?}", _e); SCLogDebug!("parse_snmp failed: {:?}", _e);
self.set_event(SNMPEvent::MalformedData); 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, _data: *mut std::os::raw::c_void,
) -> AppLayerResult { ) -> AppLayerResult {
let state = cast_pointer!(state,SNMPState); 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, 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, _data: *mut std::os::raw::c_void,
) -> AppLayerResult { ) -> AppLayerResult {
let state = cast_pointer!(state,SNMPState); 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, unsafe extern "C" fn snmp_state_get_tx(state: *mut std::os::raw::c_void,

@ -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" { extern "C" {
pub fn SCAppLayerParserReallocCtx(alproto: AppProto) -> ::std::os::raw::c_int; pub fn SCAppLayerParserReallocCtx(alproto: AppProto) -> ::std::os::raw::c_int;
} }

@ -165,6 +165,12 @@ static inline uint32_t StreamSliceGetDataLen(const StreamSlice *stream_slice)
return stream_slice->input_len; return stream_slice->input_len;
} }
typedef struct AppLayerResult {
int32_t status;
uint32_t consumed;
uint32_t needed;
} AppLayerResult;
/** \brief tx iterator prototype */ /** \brief tx iterator prototype */
typedef AppLayerGetTxIterTuple (*AppLayerGetTxIteratorFunc) typedef AppLayerGetTxIterTuple (*AppLayerGetTxIteratorFunc)
(const uint8_t ipproto, const AppProto alproto, (const uint8_t ipproto, const AppProto alproto,

Loading…
Cancel
Save