Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bindgen: use bindgen to provide Rust bindings to C - v3 #12062

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions .github/workflows/builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ jobs:
automake \
cargo-vendor \
cbindgen \
clang \
diffutils \
numactl-devel \
dpdk-devel \
Expand Down Expand Up @@ -251,6 +252,7 @@ jobs:
autoconf \
automake \
cbindgen \
clang \
diffutils \
numactl-devel \
dpdk-devel \
Expand Down Expand Up @@ -497,6 +499,7 @@ jobs:
autoconf \
automake \
cargo-vendor \
clang \
diffutils \
numactl-devel \
dpdk-devel \
Expand Down Expand Up @@ -594,6 +597,7 @@ jobs:
autoconf \
automake \
cargo-vendor \
clang \
diffutils \
numactl-devel \
dpdk-devel \
Expand Down Expand Up @@ -883,6 +887,7 @@ jobs:
cargo \
cbindgen \
ccache \
clang \
diffutils \
file-devel \
gcc \
Expand Down Expand Up @@ -1074,6 +1079,7 @@ jobs:
cargo \
cbindgen \
ccache \
clang \
diffutils \
file-devel \
gcc \
Expand Down Expand Up @@ -1325,15 +1331,15 @@ jobs:
sudo \
git \
libtool \
which
which \
clang

- name: Install Almalinux 9 extra repositories
run : |
dnf -y update
dnf -y install dnf-plugins-core epel-release
dnf config-manager --set-enabled crb


- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
- uses: ./.github/actions/install-cbindgen
- run: git config --global --add safe.directory /__w/suricata/suricata
Expand Down Expand Up @@ -2101,6 +2107,7 @@ jobs:
autoconf \
automake \
cargo \
clang \
git \
jq \
libtool \
Expand Down Expand Up @@ -2253,6 +2260,7 @@ jobs:
autoconf \
automake \
cargo \
clang \
git \
jq \
libtool \
Expand Down Expand Up @@ -2541,6 +2549,7 @@ jobs:
autoconf \
automake \
cargo \
clang \
git \
jq \
libtool \
Expand Down Expand Up @@ -2636,6 +2645,7 @@ jobs:
autoconf \
automake \
build-essential \
clang \
cmake \
curl \
dpdk-dev \
Expand Down Expand Up @@ -2821,6 +2831,7 @@ jobs:
automake \
build-essential \
cmake \
clang \
curl \
dpdk-dev \
git \
Expand Down Expand Up @@ -3107,7 +3118,7 @@ jobs:
with:
msystem: MINGW64
update: true
install: git mingw-w64-x86_64-toolchain automake1.16 automake-wrapper autoconf libtool libyaml-devel pcre2-devel jansson-devel make mingw-w64-x86_64-libyaml mingw-w64-x86_64-pcre2 mingw-w64-x86_64-rust mingw-w64-x86_64-jansson unzip p7zip python-setuptools mingw-w64-x86_64-python-yaml mingw-w64-x86_64-jq mingw-w64-x86_64-libxml2
install: git mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang automake1.16 automake-wrapper autoconf libtool libyaml-devel pcre2-devel jansson-devel make mingw-w64-x86_64-libyaml mingw-w64-x86_64-pcre2 mingw-w64-x86_64-rust mingw-w64-x86_64-jansson unzip p7zip python-setuptools mingw-w64-x86_64-python-yaml mingw-w64-x86_64-jq mingw-w64-x86_64-libxml2
# hack: install our own cbindgen system wide as we can't get the
# preinstalled one to be picked up by configure
- name: cbindgen
Expand Down Expand Up @@ -3163,7 +3174,7 @@ jobs:
with:
msystem: MINGW64
update: true
install: git mingw-w64-x86_64-toolchain automake1.16 automake-wrapper autoconf libtool libyaml-devel pcre2-devel jansson-devel make mingw-w64-x86_64-libyaml mingw-w64-x86_64-pcre2 mingw-w64-x86_64-rust mingw-w64-x86_64-jansson unzip p7zip python-setuptools mingw-w64-x86_64-python-yaml mingw-w64-x86_64-jq mingw-w64-x86_64-libxml2 libpcap-devel mingw-w64-x86_64-libpcap
install: git mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang automake1.16 automake-wrapper autoconf libtool libyaml-devel pcre2-devel jansson-devel make mingw-w64-x86_64-libyaml mingw-w64-x86_64-pcre2 mingw-w64-x86_64-rust mingw-w64-x86_64-jansson unzip p7zip python-setuptools mingw-w64-x86_64-python-yaml mingw-w64-x86_64-jq mingw-w64-x86_64-libxml2 libpcap-devel mingw-w64-x86_64-libpcap
# hack: install our own cbindgen system wide as we can't get the
# preinstalled one to be picked up by configure
- name: cbindgen
Expand Down Expand Up @@ -3207,7 +3218,7 @@ jobs:
with:
msystem: MINGW64
update: true
install: git mingw-w64-x86_64-toolchain automake1.16 automake-wrapper autoconf libtool libyaml-devel pcre2-devel jansson-devel make mingw-w64-x86_64-libyaml mingw-w64-x86_64-pcre2 mingw-w64-x86_64-rust mingw-w64-x86_64-jansson unzip p7zip python-setuptools mingw-w64-x86_64-python-yaml mingw-w64-x86_64-jq mingw-w64-x86_64-libxml2 libpcap-devel mingw-w64-x86_64-libpcap
install: git mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang automake1.16 automake-wrapper autoconf libtool libyaml-devel pcre2-devel jansson-devel make mingw-w64-x86_64-libyaml mingw-w64-x86_64-pcre2 mingw-w64-x86_64-rust mingw-w64-x86_64-jansson unzip p7zip python-setuptools mingw-w64-x86_64-python-yaml mingw-w64-x86_64-jq mingw-w64-x86_64-libxml2 libpcap-devel mingw-w64-x86_64-libpcap
# hack: install our own cbindgen system wide as we can't get the
# preinstalled one to be picked up by configure
- name: cbindgen
Expand Down Expand Up @@ -3267,6 +3278,7 @@ jobs:
dnf -y install \
autoconf \
automake \
clang \
diffutils \
numactl-devel \
dpdk-devel \
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
autoconf \
automake \
cargo-vendor \
clang \
diffutils \
numactl-devel \
dpdk-devel \
Expand Down
9 changes: 9 additions & 0 deletions rust/Cargo.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ license = "GPL-2.0-only"
description = "Suricata Rust components"
edition = "2021"
rust-version = "1.67.1"
build = "src/build.rs"

[workspace]
members = [".", "./derive"]
Expand Down Expand Up @@ -72,3 +73,11 @@ suricata-lua-sys = { version = "0.1.0-alpha.3" }
[dev-dependencies]
test-case = "~3.3.1"
hex = "~0.4.3"

[build-dependencies]
# Pin as bindgen 0.70.1 requires Rust 1.70.0+
bindgen = "=0.69.4"

# Most recent version to support Rust 1.67. 0.5.9 requires 1.70.0.
# - Not used directly but Suricata, but by bindgen.
home = "=0.5.5"
14 changes: 11 additions & 3 deletions rust/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ if RUST_CROSS_COMPILE
RUST_TARGET = --target $(host_triplet)
endif

CARGO_VARS = TOP_BUILDDIR=$(abs_top_builddir) \
TOP_SRCDIR=$(abs_top_srcdir) \
CARGO_TARGET_DIR="$(abs_top_builddir)/rust/target" \
SURICATA_LUA_SYS_HEADER_DST="$(abs_top_builddir)/rust/gen" \
CFLAGS="$(CFLAGS)"

all-local: Cargo.toml
mkdir -p $(abs_top_builddir)/rust/gen
if HAVE_CYGPATH
Expand All @@ -46,8 +52,7 @@ if HAVE_CYGPATH
else
cd $(abs_top_srcdir)/rust && \
@rustup_home@ CARGO_HOME="$(CARGO_HOME)" \
CARGO_TARGET_DIR="$(abs_top_builddir)/rust/target" \
SURICATA_LUA_SYS_HEADER_DST="$(abs_top_builddir)/rust/gen" \
$(CARGO_VARS) \
$(CARGO) build $(RELEASE) $(NIGHTLY_ARGS) \
--features "$(RUST_FEATURES)" $(RUST_TARGET)
endif
Expand Down Expand Up @@ -93,7 +98,10 @@ gen/rust-bindings.h:
endif

doc:
CARGO_HOME=$(CARGO_HOME) $(CARGO) doc --all-features --no-deps
CARGO_HOME=$(CARGO_HOME) \
$(CARGO_VARS) \
SURICATA_LUA_SYS_HEADER_DST="" $(CARGO) doc \
--all-features --no-deps

if HAVE_CBINDGEN
dist/rust-bindings.h:
Expand Down
4 changes: 2 additions & 2 deletions rust/derive/src/applayerevent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ 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::sys::SCAppLayerEventType,
) -> std::os::raw::c_int {
#crate_id::applayer::get_event_info::<#name>(event_name, event_id, 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 #crate_id::core::AppLayerEventType,
event_type: *mut #crate_id::sys::SCAppLayerEventType,
) -> std::os::raw::c_int {
#crate_id::applayer::get_event_info_by_id::<#name>(event_id, event_name, event_type)
}
Expand Down
23 changes: 13 additions & 10 deletions rust/src/applayer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@
//! Parser registration functions and common interface module.

use std;
use crate::core::{self,DetectEngineState,Flow,AppLayerEventType,AppProto,Direction};
use crate::core::{self,DetectEngineState,Flow,Direction};
use crate::filecontainer::FileContainer;
use crate::sys::SCAppLayerEventType;
use std::os::raw::{c_void,c_char,c_int};
use crate::core::SC;
use std::ffi::CStr;
use crate::core::StreamingBufferConfig;

pub use crate::sys::AppProto;

// Make the AppLayerEvent derive macro available to users importing
// AppLayerEvent from this module.
pub use suricata_derive::AppLayerEvent;
Expand Down Expand Up @@ -374,7 +377,7 @@ pub struct RustParser {
/// Function to get an event id from a description
pub get_eventinfo: Option<GetEventInfoFn>,
/// Function to get an event description from an event id
pub get_eventinfo_byid: Option<GetEventInfoByIdFn>,
pub get_eventinfo_byid: crate::sys::SCAppLayerStateGetEventInfoByIdFn,

/// Function to allocate local storage
pub localstorage_new: Option<LocalStorageNewFn>,
Expand Down Expand Up @@ -444,8 +447,8 @@ pub type StateTxFreeFn = unsafe extern "C" fn (*mut c_void, u64);
pub type StateGetTxFn = unsafe extern "C" fn (*mut c_void, u64) -> *mut c_void;
pub type StateGetTxCntFn = unsafe extern "C" fn (*mut c_void) -> u64;
pub type StateGetProgressFn = unsafe extern "C" fn (*mut c_void, u8) -> c_int;
pub type GetEventInfoFn = unsafe extern "C" fn (*const c_char, event_id: *mut u8, *mut AppLayerEventType) -> c_int;
pub type GetEventInfoByIdFn = unsafe extern "C" fn (event_id: u8, *mut *const c_char, *mut AppLayerEventType) -> c_int;
pub type GetEventInfoFn = unsafe extern "C" fn (*const c_char, event_id: *mut u8, *mut SCAppLayerEventType) -> c_int;
pub type GetEventInfoByIdFn = unsafe extern "C" fn (event_id: u8, *mut *const c_char, *mut SCAppLayerEventType) -> c_int;
pub type LocalStorageNewFn = extern "C" fn () -> *mut c_void;
pub type LocalStorageFreeFn = extern "C" fn (*mut c_void);
pub type GetTxFilesFn = unsafe extern "C" fn (*mut c_void, u8) -> AppLayerGetFileState;
Expand Down Expand Up @@ -583,13 +586,13 @@ pub trait AppLayerEvent {
unsafe extern "C" fn get_event_info(
event_name: *const std::os::raw::c_char,
event_id: *mut u8,
event_type: *mut core::AppLayerEventType,
event_type: *mut SCAppLayerEventType,
) -> 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,
event_type: *mut SCAppLayerEventType,
) -> std::os::raw::c_int;
}

Expand All @@ -612,7 +615,7 @@ pub trait AppLayerEvent {
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,
event_type: *mut SCAppLayerEventType,
) -> std::os::raw::c_int {
if event_name.is_null() {
return -1;
Expand All @@ -624,7 +627,7 @@ pub unsafe fn get_event_info<T: AppLayerEvent>(
return -1;
}
};
*event_type = core::AppLayerEventType::APP_LAYER_EVENT_TYPE_TRANSACTION;
*event_type = SCAppLayerEventType::APP_LAYER_EVENT_TYPE_TRANSACTION;
*event_id = event;
return 0;
}
Expand All @@ -635,11 +638,11 @@ pub unsafe fn get_event_info<T: AppLayerEvent>(
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,
event_type: *mut SCAppLayerEventType,
) -> 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;
*event_type = SCAppLayerEventType::APP_LAYER_EVENT_TYPE_TRANSACTION;
return 0;
}
return -1;
Expand Down
45 changes: 45 additions & 0 deletions rust/src/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// builds.rs for Suricata
//
// Currently this build.rs only uses bindgen to build some Rust
// bindings to the Suricata C code.
//
// For more info on Rust and the build.rs file, see:
// https://doc.rust-lang.org/cargo/reference/build-scripts.html
fn main() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want build-time code execution ? 😢

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have it for the derive macros. The Lua crate copies in headers at build time as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many crates do that already I know 😢

let src_dir = std::env::var("TOP_SRCDIR").unwrap_or_else(|_| "..".to_string());
let build_dir = std::env::var("TOP_BUILDDIR").unwrap_or_else(|_| "..".to_string());

// Pull in a simple header that presents no issues with bindgen at
// this time. Multiple headers can be specified.
let mut builder = bindgen::Builder::default()
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.clang_arg("-DHAVE_CONFIG_H")
.clang_arg("-D__SCFILENAME__=\"\"")
.clang_arg(format!("-I{}/src", &build_dir));

let headers = &["app-layer-types.h", "app-layer-protos.h"];
for header in headers {
builder = builder.header(format!("{}/src/{}", &src_dir, header));
}

// Patterns.
builder = builder
.allowlist_item("SCAppLayer.*")
.allowlist_item("AppProto.*");

// Rustified enums.
builder = builder
.rustified_enum("SCAppLayerEventType")
.rustified_enum("AppProtoEnum");

let bindings = builder.generate().unwrap();

// Write out the bindings. *Rules* say we should only write into
// the target directory (idiomatically the OUT_DIR env var), so
// we'll pull them into our namespace using an include!() macro
// (current in sys.rs).
let out_path = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.unwrap();
}
18 changes: 4 additions & 14 deletions rust/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,12 @@ use std;
use crate::filecontainer::*;
use crate::debug_validate_fail;

pub use crate::sys::{AppProto, AppProtoEnum};

/// Opaque C types.
pub enum DetectEngineState {}
pub enum AppLayerDecoderEvents {}

#[repr(C)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[allow(non_camel_case_types)]
pub enum AppLayerEventType {
APP_LAYER_EVENT_TYPE_TRANSACTION = 1,
APP_LAYER_EVENT_TYPE_PACKET = 2,
}

pub const STREAM_START: u8 = 0x01;
pub const STREAM_EOF: u8 = 0x02;
pub const STREAM_TOSERVER: u8 = 0x04;
Expand Down Expand Up @@ -105,11 +99,8 @@ impl From<Direction> for u8 {
}
}

// Application layer protocol identifiers (app-layer-protos.h)
pub type AppProto = u16;

pub const ALPROTO_UNKNOWN : AppProto = 0;
pub static mut ALPROTO_FAILED : AppProto = 0; // updated during init
pub const ALPROTO_UNKNOWN : AppProto = AppProtoEnum::ALPROTO_UNKNOWN as u16;
pub const ALPROTO_FAILED : AppProto = AppProtoEnum::ALPROTO_FAILED as u16;

pub const IPPROTO_TCP : u8 = 6;
pub const IPPROTO_UDP : u8 = 17;
Expand Down Expand Up @@ -252,7 +243,6 @@ pub fn init_ffi(context: &'static SuricataContext)
{
unsafe {
SC = Some(context);
ALPROTO_FAILED = StringToAppProto("failed\0".as_ptr());
}
}

Expand Down
Loading
Loading