From f5bf76c0ee4b19e7d51d3d89f535542c42c5010a Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Tue, 24 Mar 2026 01:16:08 -0600 Subject: [PATCH] examples/plugins/rust: add a rust example plugin Only demonstrates EVE callbacks for now, but I plan to turn this into a show case of a variety of callbacks a Rust plugin can do as we add Rust bindings to the ffi crate. --- .github/workflows/builds.yml | 4 ++ examples/plugins/README.md | 5 ++ examples/plugins/rust/.cargo/config.toml | 2 + examples/plugins/rust/.gitignore | 2 + examples/plugins/rust/Cargo.toml | 12 +++++ examples/plugins/rust/README.md | 5 ++ examples/plugins/rust/src/mod.rs | 60 ++++++++++++++++++++++++ 7 files changed, 90 insertions(+) create mode 100644 examples/plugins/rust/.cargo/config.toml create mode 100644 examples/plugins/rust/.gitignore create mode 100644 examples/plugins/rust/Cargo.toml create mode 100644 examples/plugins/rust/README.md create mode 100644 examples/plugins/rust/src/mod.rs diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index d2a21b5eb9..6b3dcf5cea 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -212,6 +212,10 @@ jobs: working-directory: examples/plugins/c-custom-loggers run: make clean all + - name: Build Rust example plugin + working-directory: examples/plugins/rust + run: cargo build + - name: Install Suricata and library run: make install install-headers install-library diff --git a/examples/plugins/README.md b/examples/plugins/README.md index 869d7b3ea6..49990fc0c5 100644 --- a/examples/plugins/README.md +++ b/examples/plugins/README.md @@ -14,3 +14,8 @@ for testing capture plugin loading and registration in CI. An app-layer template plugin with logging and detection. Most code copied from rust/src/applayertemplate + +## rust + +A pure Rust plugin example intended to grow into an omnibus plugin example. +Currently demonstrates plugin initialization and EVE callback registration. diff --git a/examples/plugins/rust/.cargo/config.toml b/examples/plugins/rust/.cargo/config.toml new file mode 100644 index 0000000000..46e9bc7ad6 --- /dev/null +++ b/examples/plugins/rust/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["-Clink-args=-Wl,-undefined,dynamic_lookup"] diff --git a/examples/plugins/rust/.gitignore b/examples/plugins/rust/.gitignore new file mode 100644 index 0000000000..fa8d85ac52 --- /dev/null +++ b/examples/plugins/rust/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target diff --git a/examples/plugins/rust/Cargo.toml b/examples/plugins/rust/Cargo.toml new file mode 100644 index 0000000000..0dda38d66d --- /dev/null +++ b/examples/plugins/rust/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "suricata-rust-plugin" +version = "0.1.0" +edition = "2021" + +[lib] +path = "src/mod.rs" +crate-type = ["cdylib"] + +[dependencies] +suricata-sys = { path = "../../../rust/sys" } +suricata-ffi = { path = "../../../rust/ffi" } diff --git a/examples/plugins/rust/README.md b/examples/plugins/rust/README.md new file mode 100644 index 0000000000..d541ab2e8a --- /dev/null +++ b/examples/plugins/rust/README.md @@ -0,0 +1,5 @@ +# rust example plugin + +This is a pure Rust Suricata plugin example. + +It is intended to grow into an omnibus Rust plugin example over time. diff --git a/examples/plugins/rust/src/mod.rs b/examples/plugins/rust/src/mod.rs new file mode 100644 index 0000000000..8f77b10bed --- /dev/null +++ b/examples/plugins/rust/src/mod.rs @@ -0,0 +1,60 @@ +use std::ptr::null_mut; + +use suricata_ffi::eve::{self, Flow, Packet, SCJsonBuilder, ThreadVars}; +use suricata_ffi::jsonbuilder::JsonBuilder; +use suricata_ffi::{SCLogError, SCLogNotice}; +use suricata_sys::sys::{SCEveRegisterCallback, SCPlugin}; + +unsafe extern "C" fn init() { + suricata_ffi::plugin::init(); + SCLogNotice!("Initializing rust example plugin"); + + if let Err(err) = register() { + SCLogError!("Failed to register rust example EVE callback: {}", err); + } +} + +pub fn register() -> Result<(), &'static str> { + if !unsafe { SCEveRegisterCallback(Some(log_eve_raw), null_mut()) } { + return Err("Failed to register raw EVE callback"); + } + eve::register_callback(log_eve_wrapped) +} + +unsafe extern "C" fn log_eve_raw( + _tv: *mut ThreadVars, + _p: *const Packet, + _f: *mut Flow, + jb: *mut SCJsonBuilder, + _user: *mut std::os::raw::c_void, +) { + let mut jb = JsonBuilder::from_raw(jb); + let _ = jb.open_object("foobar"); + let _ = jb.set_string("example", "eve-callback"); + let _ = jb.close(); +} + +fn log_eve_wrapped( + _tv: *mut ThreadVars, + _p: *const Packet, + f: *mut Flow, + jb: &mut JsonBuilder, +) -> Result<(), suricata_ffi::jsonbuilder::Error> { + jb.open_object("rust_wrapped")?; + jb.set_string("example", "eve-callback")?; + jb.set_string("has_flow", if f.is_null() { "false" } else { "true" })?; + jb.close()?; + Ok(()) +} + +#[no_mangle] +extern "C" fn SCPluginRegister() -> *mut SCPlugin { + suricata_ffi::plugin::Plugin { + name: "rust", + version: env!("CARGO_PKG_VERSION"), + license: "MIT", + author: "Open Information Security Foundation", + init, + } + .into_raw() +}