rust/ffi: use Flow wrapper in flow and eve callbacks

Pass the safe Flow wrapper to the flow init/update/finish callbacks and
the EVE callback instead of a raw sys::Flow pointer.

Ticket: #8599
pull/16053/head
Jason Ish 5 months ago committed by Victor Julien
parent b4043dc207
commit 8cf5d4d770

@ -104,20 +104,21 @@ The Rust wrappers register closures or function items and return
.. code-block:: rust .. code-block:: rust
use suricata_ffi::flow::{self, Flow, Packet}; use suricata_ffi::flow::{self, Flow};
use suricata_ffi::thread::ThreadVars; use suricata_ffi::thread::ThreadVars;
use suricata_sys::sys::Packet;
use suricata_ffi::SCLogNotice; use suricata_ffi::SCLogNotice;
fn flow_init(_tv: &mut ThreadVars, f: *mut Flow, _p: *const Packet) { fn flow_init(_tv: &mut ThreadVars, f: &mut Flow, _p: *const Packet) {
SCLogNotice!("flow initialized: {:p}", f); SCLogNotice!("flow initialized: {:p}", f.as_ptr());
} }
fn flow_update(_tv: &mut ThreadVars, f: *mut Flow, p: *mut Packet) { fn flow_update(_tv: &mut ThreadVars, f: &mut Flow, p: *mut Packet) {
SCLogNotice!("flow updated: {:p} packet: {:p}", f, p); SCLogNotice!("flow updated: {:p} packet: {:p}", f.as_ptr(), p);
} }
fn flow_finish(_tv: &mut ThreadVars, f: *mut Flow) { fn flow_finish(_tv: &mut ThreadVars, f: &mut Flow) {
SCLogNotice!("flow finished: {:p}", f); SCLogNotice!("flow finished: {:p}", f.as_ptr());
} }
fn register_flow_callbacks() -> Result<(), &'static str> { fn register_flow_callbacks() -> Result<(), &'static str> {

@ -1,11 +1,11 @@
use std::ptr::null_mut; use std::ptr::null_mut;
use suricata_ffi::eve::{self, SCJsonBuilder}; use suricata_ffi::eve::{self, SCJsonBuilder};
use suricata_ffi::flow; use suricata_ffi::flow::{self, Flow};
use suricata_ffi::jsonbuilder::JsonBuilder; use suricata_ffi::jsonbuilder::JsonBuilder;
use suricata_ffi::thread::{self, ThreadStorage, ThreadVars}; use suricata_ffi::thread::{self, ThreadStorage, ThreadVars};
use suricata_ffi::{SCLogError, SCLogNotice, SCLogWarning}; use suricata_ffi::{SCLogError, SCLogNotice, SCLogWarning};
use suricata_sys::sys::{self, Flow, Packet, SCEveRegisterCallback, SCPlugin}; use suricata_sys::sys::{self, Packet, SCEveRegisterCallback, SCPlugin};
/// Per-thread state stored in Suricata thread storage. /// Per-thread state stored in Suricata thread storage.
#[derive(Default)] #[derive(Default)]
@ -59,7 +59,7 @@ fn register_thread_callbacks(storage: ThreadStorage<ThreadState>) -> Result<(),
unsafe extern "C" fn log_eve_raw( unsafe extern "C" fn log_eve_raw(
_tv: *mut sys::ThreadVars, _tv: *mut sys::ThreadVars,
_p: *const Packet, _p: *const Packet,
_f: *mut Flow, _f: *mut sys::Flow,
jb: *mut SCJsonBuilder, jb: *mut SCJsonBuilder,
_user: *mut std::os::raw::c_void, _user: *mut std::os::raw::c_void,
) { ) {
@ -72,12 +72,12 @@ unsafe extern "C" fn log_eve_raw(
fn log_eve_wrapped( fn log_eve_wrapped(
_tv: &mut ThreadVars, _tv: &mut ThreadVars,
_p: *const Packet, _p: *const Packet,
f: *mut Flow, f: Option<&mut Flow>,
jb: &mut JsonBuilder, jb: &mut JsonBuilder,
) -> Result<(), suricata_ffi::jsonbuilder::Error> { ) -> Result<(), suricata_ffi::jsonbuilder::Error> {
jb.open_object("rust_wrapped")?; jb.open_object("rust_wrapped")?;
jb.set_string("example", "eve-callback")?; jb.set_string("example", "eve-callback")?;
jb.set_string("has_flow", if f.is_null() { "false" } else { "true" })?; jb.set_string("has_flow", if f.is_some() { "true" } else { "false" })?;
jb.close()?; jb.close()?;
Ok(()) Ok(())
} }
@ -96,7 +96,7 @@ fn on_thread_init(storage: ThreadStorage<ThreadState>, tv: &mut ThreadVars) {
fn log_flow_init( fn log_flow_init(
storage: ThreadStorage<ThreadState>, storage: ThreadStorage<ThreadState>,
tv: &mut ThreadVars, tv: &mut ThreadVars,
f: *mut Flow, f: &mut Flow,
_p: *const Packet, _p: *const Packet,
) { ) {
// Count flows seen by this thread using the per-thread storage. // Count flows seen by this thread using the per-thread storage.
@ -112,21 +112,21 @@ fn log_flow_init(
}; };
SCLogNotice!( SCLogNotice!(
"rust example flow init callback: flow={:p}, thread_flows={}", "rust example flow init callback: flow={:p}, thread_flows={}",
f, f.as_ptr(),
flows flows
); );
} }
fn log_flow_update(_tv: &mut ThreadVars, _f: *mut Flow, _p: *mut Packet) { fn log_flow_update(_tv: &mut ThreadVars, f: &mut Flow, _p: *mut Packet) {
SCLogNotice!( SCLogNotice!(
"rust example flow update callback: flow={:p}, packet={:p}", "rust example flow update callback: flow={:p}, packet={:p}",
_f, f.as_ptr(),
_p _p
); );
} }
fn log_flow_finish(_tv: &mut ThreadVars, _f: *mut Flow) { fn log_flow_finish(_tv: &mut ThreadVars, f: &mut Flow) {
SCLogNotice!("rust example flow finish callback: flow={:p}", _f); SCLogNotice!("rust example flow finish callback: flow={:p}", f.as_ptr());
} }
#[no_mangle] #[no_mangle]

@ -23,8 +23,9 @@ use suricata_sys::sys::{
SCEveFileTypeThreadDeinitFunc, SCEveFileTypeThreadInitFunc, SCEveFileTypeWriteFunc, SCEveFileTypeThreadDeinitFunc, SCEveFileTypeThreadInitFunc, SCEveFileTypeWriteFunc,
SCEveRegisterCallback, SCRegisterEveFileType, SCEveRegisterCallback, SCRegisterEveFileType,
}; };
pub use suricata_sys::sys::{Flow, Packet, SCEveUserCallbackFn, SCJsonBuilder}; pub use suricata_sys::sys::{Packet, SCEveUserCallbackFn, SCJsonBuilder};
use crate::flow::Flow;
use crate::thread::ThreadVars; use crate::thread::ThreadVars;
pub struct EveFileType { pub struct EveFileType {
@ -82,7 +83,7 @@ impl EveFileType {
/// The callback receives: /// The callback receives:
/// - `tv`: the `ThreadVars` for the thread performing the logging /// - `tv`: the `ThreadVars` for the thread performing the logging
/// - `p`: the `Packet`, if available /// - `p`: the `Packet`, if available
/// - `f`: the `Flow`, if available /// - `f`: the `Flow`, if available (`None` when no flow is associated)
/// - `jb`: the JSON builder for the current EVE record /// - `jb`: the JSON builder for the current EVE record
/// ///
/// This API is intended for plugin and library users. /// This API is intended for plugin and library users.
@ -115,7 +116,7 @@ where
F: Fn( F: Fn(
&mut ThreadVars, &mut ThreadVars,
*const Packet, *const Packet,
*mut Flow, Option<&mut Flow>,
&mut crate::jsonbuilder::JsonBuilder, &mut crate::jsonbuilder::JsonBuilder,
) -> Result<(), crate::jsonbuilder::Error> ) -> Result<(), crate::jsonbuilder::Error>
+ Send + Send
@ -136,13 +137,13 @@ where
/// Internal wrapper used to adapt the C EVE callback to a Rust /// Internal wrapper used to adapt the C EVE callback to a Rust
/// closure callback. /// closure callback.
unsafe extern "C" fn callback_wrapper<F>( unsafe extern "C" fn callback_wrapper<F>(
tv: *mut sys::ThreadVars, p: *const Packet, f: *mut Flow, jb: *mut SCJsonBuilder, tv: *mut sys::ThreadVars, p: *const Packet, f: *mut sys::Flow, jb: *mut SCJsonBuilder,
user: *mut c_void, user: *mut c_void,
) where ) where
F: Fn( F: Fn(
&mut ThreadVars, &mut ThreadVars,
*const Packet, *const Packet,
*mut Flow, Option<&mut Flow>,
&mut crate::jsonbuilder::JsonBuilder, &mut crate::jsonbuilder::JsonBuilder,
) -> Result<(), crate::jsonbuilder::Error> ) -> Result<(), crate::jsonbuilder::Error>
+ Send + Send
@ -151,9 +152,14 @@ unsafe extern "C" fn callback_wrapper<F>(
{ {
let callback = &*(user as *const F); let callback = &*(user as *const F);
let mut tv = ThreadVars::from_ptr(tv); let mut tv = ThreadVars::from_ptr(tv);
let mut flow = if f.is_null() {
None
} else {
Some(Flow::from_ptr(f))
};
let mut jb = crate::jsonbuilder::JsonBuilder::from_raw(jb); let mut jb = crate::jsonbuilder::JsonBuilder::from_raw(jb);
let mark = jb.get_mark(); let mark = jb.get_mark();
if callback(&mut tv, p, f, &mut jb).is_err() { if callback(&mut tv, p, flow.as_mut(), &mut jb).is_err() {
let _ = jb.restore_mark(&mark); let _ = jb.restore_mark(&mark);
} }
} }

@ -69,7 +69,7 @@ impl<'a> Flow<'a> {
/// The callback must not panic. /// The callback must not panic.
pub fn register_init_callback<F>(callback: F) -> Result<(), &'static str> pub fn register_init_callback<F>(callback: F) -> Result<(), &'static str>
where where
F: Fn(&mut ThreadVars, *mut sys::Flow, *const Packet) + Send + Sync + 'static, F: Fn(&mut ThreadVars, &mut Flow, *const Packet) + Send + Sync + 'static,
{ {
let user = Box::into_raw(Box::new(callback)) as *mut c_void; let user = Box::into_raw(Box::new(callback)) as *mut c_void;
if unsafe { SCFlowRegisterInitCallback(Some(init_callback_wrapper::<F>), user) } { if unsafe { SCFlowRegisterInitCallback(Some(init_callback_wrapper::<F>), user) } {
@ -98,7 +98,7 @@ where
/// The callback must not panic. /// The callback must not panic.
pub fn register_update_callback<F>(callback: F) -> Result<(), &'static str> pub fn register_update_callback<F>(callback: F) -> Result<(), &'static str>
where where
F: Fn(&mut ThreadVars, *mut sys::Flow, *mut Packet) + Send + Sync + 'static, F: Fn(&mut ThreadVars, &mut Flow, *mut Packet) + Send + Sync + 'static,
{ {
let user = Box::into_raw(Box::new(callback)) as *mut c_void; let user = Box::into_raw(Box::new(callback)) as *mut c_void;
if unsafe { SCFlowRegisterUpdateCallback(Some(update_callback_wrapper::<F>), user) } { if unsafe { SCFlowRegisterUpdateCallback(Some(update_callback_wrapper::<F>), user) } {
@ -125,7 +125,7 @@ where
/// The callback must not panic. /// The callback must not panic.
pub fn register_finish_callback<F>(callback: F) -> Result<(), &'static str> pub fn register_finish_callback<F>(callback: F) -> Result<(), &'static str>
where where
F: Fn(&mut ThreadVars, *mut sys::Flow) + Send + Sync + 'static, F: Fn(&mut ThreadVars, &mut Flow) + Send + Sync + 'static,
{ {
let user = Box::into_raw(Box::new(callback)) as *mut c_void; let user = Box::into_raw(Box::new(callback)) as *mut c_void;
if unsafe { SCFlowRegisterFinishCallback(Some(finish_callback_wrapper::<F>), user) } { if unsafe { SCFlowRegisterFinishCallback(Some(finish_callback_wrapper::<F>), user) } {
@ -141,29 +141,32 @@ where
unsafe extern "C" fn init_callback_wrapper<F>( unsafe extern "C" fn init_callback_wrapper<F>(
tv: *mut sys::ThreadVars, f: *mut sys::Flow, p: *const Packet, user: *mut c_void, tv: *mut sys::ThreadVars, f: *mut sys::Flow, p: *const Packet, user: *mut c_void,
) where ) where
F: Fn(&mut ThreadVars, *mut sys::Flow, *const Packet) + Send + Sync + 'static, F: Fn(&mut ThreadVars, &mut Flow, *const Packet) + Send + Sync + 'static,
{ {
let callback = &*(user as *const F); let callback = &*(user as *const F);
let mut tv = ThreadVars::from_ptr(tv); let mut tv = ThreadVars::from_ptr(tv);
callback(&mut tv, f, p); let mut f = Flow::from_ptr(f);
callback(&mut tv, &mut f, p);
} }
unsafe extern "C" fn update_callback_wrapper<F>( unsafe extern "C" fn update_callback_wrapper<F>(
tv: *mut sys::ThreadVars, f: *mut sys::Flow, p: *mut Packet, user: *mut c_void, tv: *mut sys::ThreadVars, f: *mut sys::Flow, p: *mut Packet, user: *mut c_void,
) where ) where
F: Fn(&mut ThreadVars, *mut sys::Flow, *mut Packet) + Send + Sync + 'static, F: Fn(&mut ThreadVars, &mut Flow, *mut Packet) + Send + Sync + 'static,
{ {
let callback = &*(user as *const F); let callback = &*(user as *const F);
let mut tv = ThreadVars::from_ptr(tv); let mut tv = ThreadVars::from_ptr(tv);
callback(&mut tv, f, p); let mut f = Flow::from_ptr(f);
callback(&mut tv, &mut f, p);
} }
unsafe extern "C" fn finish_callback_wrapper<F>( unsafe extern "C" fn finish_callback_wrapper<F>(
tv: *mut sys::ThreadVars, f: *mut sys::Flow, user: *mut c_void, tv: *mut sys::ThreadVars, f: *mut sys::Flow, user: *mut c_void,
) where ) where
F: Fn(&mut ThreadVars, *mut sys::Flow) + Send + Sync + 'static, F: Fn(&mut ThreadVars, &mut Flow) + Send + Sync + 'static,
{ {
let callback = &*(user as *const F); let callback = &*(user as *const F);
let mut tv = ThreadVars::from_ptr(tv); let mut tv = ThreadVars::from_ptr(tv);
callback(&mut tv, f); let mut f = Flow::from_ptr(f);
callback(&mut tv, &mut f);
} }

Loading…
Cancel
Save