]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust: wrapper around C logging, and "context"
authorJason Ish <ish@unx.ca>
Wed, 26 Apr 2017 22:33:47 +0000 (16:33 -0600)
committerJason Ish <ish@unx.ca>
Mon, 5 Jun 2017 20:57:21 +0000 (14:57 -0600)
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.

rust/src/core.rs [new file with mode: 0644]
rust/src/lib.rs
rust/src/log.rs
src/rust.h
src/suricata.c
src/util-debug.c

diff --git a/rust/src/core.rs b/rust/src/core.rs
new file mode 100644 (file)
index 0000000..f92f3f0
--- /dev/null
@@ -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);
+        }
+    }
+}
index 52ee7128c26a8f7fd7c8860884fa283ba17f15f9..cf439d460706009d1f0832b76fdddf28e56493b2 100644 (file)
@@ -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;
index bf4ad73e3f8c27536240721526f08c6a968c9be9..19b78cf6c3952c08e6e978c20c6116d18d722df5 100644 (file)
 
 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 <rust> 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;
     }
index f346cb2027bc652f9865d8afec131a92f6e36677..68314cbd771fc2e538f19bef4d2e80fec4b23955 100644 (file)
  * 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__ */
index 6604601bf300ee3ec8047bff943c8a53a25f6111..7ab3ec3af7b4567d3db97ccaddf92deac283461a 100644 (file)
 
 #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 */
index a5bf99ce83590527ef3f70a451076152cb248237..027538a1f121c857cd29f2c8ea5584460cbac81e 100644 (file)
@@ -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;