From: Jason Ish Date: Wed, 26 Apr 2017 22:33:47 +0000 (-0600) Subject: rust: wrapper around C logging, and "context" X-Git-Tag: suricata-4.0.0-beta1~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=94032d3ada84e1d5a78ab96f02a411d33253c3b9;p=thirdparty%2Fsuricata.git rust: wrapper around C logging, and "context" Where the context is a struct passed from C with pointers to all the functions that may be called. Instead of referencing C functions directly, wrap them in function pointers so pure Rust unit tests can still run. --- diff --git a/rust/src/core.rs b/rust/src/core.rs new file mode 100644 index 0000000000..f92f3f0b01 --- /dev/null +++ b/rust/src/core.rs @@ -0,0 +1,127 @@ +/* Copyright (C) 2017 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +// This file exposes items from the core "C" code to Rust. + +extern crate libc; + +/// Opaque C types. +pub enum Flow {} +pub enum DetectEngineState {} +pub enum AppLayerDecoderEvents {} + +// From stream.h. +pub const STREAM_TOSERVER: u8 = 0x04; +pub const STREAM_TOCLIENT: u8 = 0x08; + +// +// Function types for calls into C. +// + +#[allow(non_snake_case)] +pub type SCLogMessageFunc = + extern "C" fn(level: libc::c_int, + filename: *const libc::c_char, + line: libc::c_uint, + function: *const libc::c_char, + code: libc::c_int, + message: *const libc::c_char) -> libc::c_int; + +pub type DetectEngineStateFreeFunc = + extern "C" fn(state: *mut DetectEngineState); + +pub type AppLayerDecoderEventsSetEventRawFunc = + extern "C" fn (events: *mut *mut AppLayerDecoderEvents, + event: libc::uint8_t); + +pub type AppLayerDecoderEventsFreeEventsFunc = + extern "C" fn (events: *mut *mut AppLayerDecoderEvents); + +// A Suricata context that is passed in from C. This is alternative to +// using functions from Suricata directly, so they can be wrapped so +// Rust unit tests will still compile when they are not linked +// directly to the real function. +// +// This might add a little too much complexity to keep pure Rust test +// cases working. +#[allow(non_snake_case)] +#[repr(C)] +pub struct SuricataContext { + SCLogMessage: SCLogMessageFunc, + DetectEngineStateFree: DetectEngineStateFreeFunc, + AppLayerDecoderEventsSetEventRaw: AppLayerDecoderEventsSetEventRawFunc, + AppLayerDecoderEventsFreeEvents: AppLayerDecoderEventsFreeEventsFunc, +} + +pub static mut SC: Option<&'static SuricataContext> = None; + +#[no_mangle] +pub extern "C" fn rs_init(context: &'static mut SuricataContext) +{ + unsafe { + SC = Some(context); + } +} + +/// SCLogMessage wrapper. +pub fn sc_log_message(level: libc::c_int, + filename: *const libc::c_char, + line: libc::c_uint, + function: *const libc::c_char, + code: libc::c_int, + message: *const libc::c_char) -> libc::c_int +{ + unsafe { + if let Some(c) = SC { + return (c.SCLogMessage)(level, filename, line, function, + code, message); + } + } + return 0; +} + +/// DetectEngineStateFree wrapper. +pub fn sc_detect_engine_state_free(state: *mut DetectEngineState) +{ + unsafe { + if let Some(c) = SC { + (c.DetectEngineStateFree)(state); + } + } +} + +/// AppLayerDecoderEventsSetEventRaw wrapper. +pub fn sc_app_layer_decoder_events_set_event_raw( + events: *mut *mut AppLayerDecoderEvents, event: libc::uint8_t) +{ + unsafe { + if let Some(c) = SC { + (c.AppLayerDecoderEventsSetEventRaw)(events, event); + } + } +} + +/// AppLayerDecoderEventsFreeEvents wrapper. +pub fn sc_app_layer_decoder_events_free_events( + events: *mut *mut AppLayerDecoderEvents) +{ + unsafe { + if let Some(c) = SC { + (c.AppLayerDecoderEventsFreeEvents)(events); + } + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 52ee7128c2..cf439d4607 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,6 +1,24 @@ +/* Copyright (C) 2017 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + #[macro_use] pub mod log; +pub mod core; pub mod conf; pub mod dns; pub mod json; diff --git a/rust/src/log.rs b/rust/src/log.rs index bf4ad73e3f..19b78cf6c3 100644 --- a/rust/src/log.rs +++ b/rust/src/log.rs @@ -17,10 +17,11 @@ extern crate libc; -use std::os::raw::c_char; use std::ffi::{CString}; use std::path::Path; +use core::*; + pub enum Level { NotSet = -1, None = 0, @@ -38,15 +39,6 @@ pub enum Level { pub static mut LEVEL: i32 = Level::NotSet as i32; -extern { - fn SCLogMessage(level: libc::c_int, - filename: *const c_char, - line: libc::c_uint, - function: *const c_char, - code: libc::c_int, - message: *const c_char) -> libc::c_int; -} - pub fn get_log_level() -> i32 { unsafe { LEVEL @@ -67,15 +59,12 @@ pub fn sclog(level: Level, file: &str, line: u32, function: &str, code: i32, message: &str) { let filename = basename(file); - - unsafe { - SCLogMessage(level as i32, - CString::new(filename).unwrap().as_ptr(), - line, - CString::new(function).unwrap().as_ptr(), - code, - CString::new(message).unwrap().as_ptr()); - } + sc_log_message(level as i32, + CString::new(filename).unwrap().as_ptr(), + line, + CString::new(function).unwrap().as_ptr(), + code, + CString::new(message).unwrap().as_ptr()); } /// Return the function name, but for now just return as Rust @@ -132,7 +121,7 @@ macro_rules!SCLogDebug { } #[no_mangle] -pub extern "C" fn rs_log_init(level: i32) { +pub extern "C" fn rs_log_set_level(level: i32) { unsafe { LEVEL = level; } diff --git a/src/rust.h b/src/rust.h index f346cb2027..68314cbd77 100644 --- a/src/rust.h +++ b/src/rust.h @@ -15,5 +15,18 @@ * 02110-1301, USA. */ -void rs_log_init(int32_t level); +#ifndef __RUST_H__ +#define __RUST_H__ + +typedef struct SuricataContext_ { + SCError (*SCLogMessage)(const SCLogLevel, const char *, const unsigned int, + const char *, const SCError, const char *message); + void (*DetectEngineStateFree)(DetectEngineState *); + void (*AppLayerDecoderEventsSetEventRaw)(AppLayerDecoderEvents **, + uint8_t); + void (*AppLayerDecoderEventsFreeEvents)(AppLayerDecoderEvents **); +} SuricataContext; + void rs_dns_init(void); + +#endif /* !__RUST_H__ */ diff --git a/src/suricata.c b/src/suricata.c index 6604601bf3..7ab3ec3af7 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -173,6 +173,11 @@ #include "util-lua.h" +#ifdef HAVE_RUST +#include "rust.h" +#include "rust-core.h" +#endif + /* * we put this here, because we only use it here in main. */ @@ -2774,6 +2779,16 @@ int main(int argc, char **argv) SCInstance suri; SCInstanceInit(&suri, argv[0]); +#ifdef HAVE_RUST + SuricataContext context; + context.SCLogMessage = SCLogMessage; + context.DetectEngineStateFree = DetectEngineStateFree; + context.AppLayerDecoderEventsSetEventRaw = + AppLayerDecoderEventsSetEventRaw; + context.AppLayerDecoderEventsFreeEvents = AppLayerDecoderEventsFreeEvents; + rs_init(&context); +#endif + SC_ATOMIC_INIT(engine_stage); /* initialize the logging subsys */ diff --git a/src/util-debug.c b/src/util-debug.c index a5bf99ce83..027538a1f1 100644 --- a/src/util-debug.c +++ b/src/util-debug.c @@ -44,7 +44,7 @@ #include "util-syslog.h" #ifdef HAVE_RUST -#include "rust.h" +#include "rust-log.h" #endif #include "conf.h" @@ -1261,7 +1261,7 @@ void SCLogInitLogModule(SCLogInitData *sc_lid) //SCOutputPrint(sc_did->startup_message); #ifdef HAVE_RUST - rs_log_init(sc_log_global_log_level); + rs_log_set_level(sc_log_global_log_level); #endif return;