rust/ffi: move AppLayerEvent to ffi

Ticket: 7666
pull/15329/head
Philippe Antoine 2 months ago committed by Victor Julien
parent 5bbe99188b
commit 5ed394b26b

@ -12,6 +12,7 @@ libc = "~0.2.82"
suricata = { path = "../../../rust/" }
suricata-sys = { path = "../../../rust/sys" }
suricata-ffi = { path = "../../../rust/ffi" }
suricata-derive = { path = "../../../rust/derive" }
[features]
default = ["suricata8"]

@ -26,9 +26,10 @@ use std;
use std::collections::VecDeque;
use std::ffi::CString;
use std::os::raw::{c_char, c_int, c_void};
use suricata::applayer::{AppLayerEvent, AppLayerTxData};
use suricata::applayer::AppLayerTxData;
use suricata_derive::AppLayerEvent;
use suricata_ffi::applayer::{
state_get_tx_iterator, AppLayerResultRust, State, StreamSliceRust, Transaction,
state_get_tx_iterator, AppLayerEvent, AppLayerResultRust, State, StreamSliceRust, Transaction,
APP_LAYER_PARSER_EOF_TC, APP_LAYER_PARSER_EOF_TS, APP_LAYER_PARSER_OPT_ACCEPT_GAPS,
};
use suricata_ffi::conf::conf_get;

@ -52,12 +52,12 @@ pub fn derive_app_layer_event(input: TokenStream) -> TokenStream {
// Suricata name space as "suricata". Check the CARGO_PKG_NAME environment variable to
// determine what identifier to setup.
let is_suricata = std::env::var("CARGO_PKG_NAME")
.map(|var| var == "suricata")
.map(|var| var == "suricata_ffi")
.unwrap_or(false);
let crate_id = if is_suricata {
syn::Ident::new("crate", proc_macro2::Span::call_site())
} else {
syn::Ident::new("suricata", proc_macro2::Span::call_site())
syn::Ident::new("suricata_ffi", proc_macro2::Span::call_site())
};
let expanded = quote! {
@ -91,7 +91,7 @@ pub fn derive_app_layer_event(input: TokenStream) -> TokenStream {
unsafe extern "C" fn get_event_info(
event_name: *const std::os::raw::c_char,
event_id: *mut u8,
event_type: *mut #crate_id::core::AppLayerEventType,
event_type: *mut #crate_id::applayer::AppLayerEventType,
) -> std::os::raw::c_int {
#crate_id::applayer::get_event_info::<#name>(event_name, event_id, event_type)
}
@ -99,7 +99,7 @@ pub fn derive_app_layer_event(input: TokenStream) -> TokenStream {
unsafe extern "C" fn get_event_info_by_id(
event_id: u8,
event_name: *mut *const std::os::raw::c_char,
event_type: *mut #crate_id::core::AppLayerEventType,
event_type: *mut #crate_id::applayer::AppLayerEventType,
) -> std::os::raw::c_int {
#crate_id::applayer::get_event_info_by_id::<#name>(event_id, event_name, event_type)
}

@ -18,6 +18,8 @@
//! App-layer utils.
use crate::cast_pointer;
use std::ffi::CStr;
pub use suricata_sys::sys::AppLayerEventType;
use suricata_sys::sys::{
AppLayerGetTxIterState, AppLayerGetTxIterTuple, AppLayerResult, AppProto, StreamSlice,
};
@ -227,3 +229,102 @@ pub unsafe extern "C" fn state_get_tx_iterator<S: State<Tx>, Tx: Transaction>(
let state = cast_pointer!(state, S);
state.get_transaction_iterator(min_tx_id, &mut (*istate).un.u64_)
}
/// AppLayerEvent trait that will be implemented on enums that
/// derive AppLayerEvent.
pub trait AppLayerEvent {
/// Return the enum variant of the given ID.
fn from_id(id: u8) -> Option<Self>
where
Self: std::marker::Sized;
/// Convert the enum variant to a C-style string (suffixed with \0).
fn to_cstring(&self) -> &str;
/// Return the enum variant for the given name.
fn from_string(s: &str) -> Option<Self>
where
Self: std::marker::Sized;
/// Return the ID value of the enum variant.
fn as_u8(&self) -> u8;
/// # Safety
///
/// Caller should provide a valid cstring for event_name.
/// a non-null pointer for event_id
/// and a non-null pointer for event_type
unsafe extern "C" fn get_event_info(
event_name: *const std::os::raw::c_char, event_id: *mut u8,
event_type: *mut AppLayerEventType,
) -> std::os::raw::c_int;
/// # Safety
///
/// Caller should provide
/// a non-null pointer for event_name
/// and a non-null pointer for event_type
unsafe extern "C" fn get_event_info_by_id(
event_id: u8, event_name: *mut *const std::os::raw::c_char,
event_type: *mut AppLayerEventType,
) -> std::os::raw::c_int;
}
/// Generic `get_info_info` implementation for enums implementing
/// AppLayerEvent.
///
/// Normally usage of this function will be generated by
/// derive(AppLayerEvent), for example:
///
/// ```rust,ignore
/// #[derive(AppLayerEvent)]
/// enum AppEvent {
/// EventOne,
/// EventTwo,
/// }
///
/// get_event_info::<AppEvent>(...)
/// ```
///
/// # Safety
///
/// Caller should provide a valid cstring for event_name.
/// a non-null pointer for event_id
/// and a non-null pointer for event_type
#[inline(always)]
pub unsafe fn get_event_info<T: AppLayerEvent>(
event_name: *const std::os::raw::c_char, event_id: *mut u8, event_type: *mut AppLayerEventType,
) -> std::os::raw::c_int {
if event_name.is_null() {
return -1;
}
let event = match CStr::from_ptr(event_name).to_str().map(T::from_string) {
Ok(Some(event)) => event.as_u8(),
_ => {
return -1;
}
};
*event_type = AppLayerEventType::APP_LAYER_EVENT_TYPE_TRANSACTION;
*event_id = event;
0
}
/// Generic `get_info_info_by_id` implementation for enums implementing
/// AppLayerEvent.
/// # Safety
///
/// Caller should provide
/// a non-null pointer for event_name
/// and a non-null pointer for event_type
#[inline(always)]
pub unsafe fn get_event_info_by_id<T: AppLayerEvent>(
event_id: u8, event_name: *mut *const std::os::raw::c_char, event_type: *mut AppLayerEventType,
) -> std::os::raw::c_int {
if let Some(e) = T::from_id(event_id) {
*event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char;
*event_type = AppLayerEventType::APP_LAYER_EVENT_TYPE_TRANSACTION;
return 0;
}
-1
}

@ -18,11 +18,10 @@
//! Parser registration functions and common interface module.
use std;
use crate::core::{self,AppLayerEventType, STREAM_TOSERVER};
use crate::core::STREAM_TOSERVER;
use crate::direction::Direction;
use crate::flow::Flow;
use std::os::raw::{c_void,c_char,c_int};
use std::ffi::CStr;
// Make the AppLayerEvent derive macro available to users importing
// AppLayerEvent from this module.
@ -134,7 +133,7 @@ pub unsafe extern "C" fn SCTxDataUpdateFileFlags(txd: &mut suricata_sys::sys::Ap
pub use suricata_ffi::{export_tx_data_get, export_state_data_get};
pub use suricata_ffi::applayer::{AppLayerResultRust, StreamSliceRust};
pub use suricata_ffi::applayer::{AppLayerEvent, AppLayerEventType, AppLayerResultRust, StreamSliceRust};
/// Rust parser declaration
#[repr(C)]
@ -329,86 +328,6 @@ pub const _APP_LAYER_TX_INSPECTED_TS: u8 = BIT_U8!(2);
pub const _APP_LAYER_TX_INSPECTED_TC: u8 = BIT_U8!(3);
pub const APP_LAYER_TX_ACCEPT: u8 = BIT_U8!(4);
/// AppLayerEvent trait that will be implemented on enums that
/// derive AppLayerEvent.
pub trait AppLayerEvent {
/// Return the enum variant of the given ID.
fn from_id(id: u8) -> Option<Self> where Self: std::marker::Sized;
/// Convert the enum variant to a C-style string (suffixed with \0).
fn to_cstring(&self) -> &str;
/// Return the enum variant for the given name.
fn from_string(s: &str) -> Option<Self> where Self: std::marker::Sized;
/// Return the ID value of the enum variant.
fn as_u8(&self) -> u8;
unsafe extern "C" fn get_event_info(
event_name: *const std::os::raw::c_char,
event_id: *mut u8,
event_type: *mut core::AppLayerEventType,
) -> std::os::raw::c_int;
unsafe extern "C" fn get_event_info_by_id(
event_id: u8,
event_name: *mut *const std::os::raw::c_char,
event_type: *mut core::AppLayerEventType,
) -> std::os::raw::c_int;
}
/// Generic `get_info_info` implementation for enums implementing
/// AppLayerEvent.
///
/// Normally usage of this function will be generated by
/// derive(AppLayerEvent), for example:
///
/// ```rust,ignore
/// #[derive(AppLayerEvent)]
/// enum AppEvent {
/// EventOne,
/// EventTwo,
/// }
///
/// get_event_info::<AppEvent>(...)
/// ```
#[inline(always)]
pub unsafe fn get_event_info<T: AppLayerEvent>(
event_name: *const std::os::raw::c_char,
event_id: *mut u8,
event_type: *mut core::AppLayerEventType,
) -> std::os::raw::c_int {
if event_name.is_null() {
return -1;
}
let event = match CStr::from_ptr(event_name).to_str().map(T::from_string) {
Ok(Some(event)) => event.as_u8(),
_ => {
return -1;
}
};
*event_type = core::AppLayerEventType::APP_LAYER_EVENT_TYPE_TRANSACTION;
*event_id = event;
return 0;
}
/// Generic `get_info_info_by_id` implementation for enums implementing
/// AppLayerEvent.
#[inline(always)]
pub unsafe fn get_event_info_by_id<T: AppLayerEvent>(
event_id: u8,
event_name: *mut *const std::os::raw::c_char,
event_type: *mut core::AppLayerEventType,
) -> std::os::raw::c_int {
if let Some(e) = T::from_id(event_id) {
*event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char;
*event_type = core::AppLayerEventType::APP_LAYER_EVENT_TYPE_TRANSACTION;
return 0;
}
return -1;
}
pub use suricata_ffi::applayer::{state_get_tx_iterator, State, Transaction};
/// AppLayerFrameType trait.

@ -35,7 +35,7 @@ pub enum FtpEvent {
pub unsafe extern "C" fn ftp_get_event_info(
event_name: *const c_char, event_id: *mut u8, event_type: *mut AppLayerEventType,
) -> c_int {
crate::applayer::get_event_info::<FtpEvent>(event_name, event_id, event_type)
suricata_ffi::applayer::get_event_info::<FtpEvent>(event_name, event_id, event_type)
}
/// Wrapper around the Rust generic function for get_event_info_by_id.
@ -46,5 +46,5 @@ pub unsafe extern "C" fn ftp_get_event_info(
pub unsafe extern "C" fn ftp_get_event_info_by_id(
event_id: u8, event_name: *mut *const c_char, event_type: *mut AppLayerEventType,
) -> c_int {
crate::applayer::get_event_info_by_id::<FtpEvent>(event_id, event_name, event_type) as c_int
suricata_ffi::applayer::get_event_info_by_id::<FtpEvent>(event_id, event_name, event_type) as c_int
}

Loading…
Cancel
Save