From 5ed394b26b0da5a851c9ce9c08c3779887424957 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 30 Apr 2026 20:21:25 +0200 Subject: [PATCH] rust/ffi: move AppLayerEvent to ffi Ticket: 7666 --- examples/plugins/altemplate/Cargo.toml | 1 + examples/plugins/altemplate/src/template.rs | 5 +- rust/derive/src/applayerevent.rs | 8 +- rust/ffi/src/applayer.rs | 101 ++++++++++++++++++++ rust/src/applayer.rs | 85 +--------------- rust/src/ftp/event.rs | 4 +- 6 files changed, 113 insertions(+), 91 deletions(-) diff --git a/examples/plugins/altemplate/Cargo.toml b/examples/plugins/altemplate/Cargo.toml index e8efb2f5fd..568f90f6a9 100644 --- a/examples/plugins/altemplate/Cargo.toml +++ b/examples/plugins/altemplate/Cargo.toml @@ -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"] diff --git a/examples/plugins/altemplate/src/template.rs b/examples/plugins/altemplate/src/template.rs index 79976c4f87..14a76a9d92 100644 --- a/examples/plugins/altemplate/src/template.rs +++ b/examples/plugins/altemplate/src/template.rs @@ -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; diff --git a/rust/derive/src/applayerevent.rs b/rust/derive/src/applayerevent.rs index 528e84d5b7..ce6a099d4c 100644 --- a/rust/derive/src/applayerevent.rs +++ b/rust/derive/src/applayerevent.rs @@ -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) } diff --git a/rust/ffi/src/applayer.rs b/rust/ffi/src/applayer.rs index 84676de8e7..876a485f44 100644 --- a/rust/ffi/src/applayer.rs +++ b/rust/ffi/src/applayer.rs @@ -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, 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 + 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 + 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::(...) +/// ``` +/// +/// # 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( + 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( + 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 +} diff --git a/rust/src/applayer.rs b/rust/src/applayer.rs index 0907ce1b1d..1460509535 100644 --- a/rust/src/applayer.rs +++ b/rust/src/applayer.rs @@ -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 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 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::(...) -/// ``` -#[inline(always)] -pub unsafe 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 { - 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( - 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. diff --git a/rust/src/ftp/event.rs b/rust/src/ftp/event.rs index cc327369d8..d7ee6969d6 100644 --- a/rust/src/ftp/event.rs +++ b/rust/src/ftp/event.rs @@ -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::(event_name, event_id, event_type) + suricata_ffi::applayer::get_event_info::(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::(event_id, event_name, event_type) as c_int + suricata_ffi::applayer::get_event_info_by_id::(event_id, event_name, event_type) as c_int }