]> git.ipfire.org Git - people/ms/suricata.git/commitdiff
rust/applayer: provide generic event info functions
authorJason Ish <jason.ish@oisf.net>
Wed, 18 Nov 2020 17:57:22 +0000 (11:57 -0600)
committerVictor Julien <victor@inliniac.net>
Wed, 1 Sep 2021 06:33:52 +0000 (08:33 +0200)
Provide generic functions for get_event_info and
get_event_info_by_id. These functions can be used by any app-layer
event enum that implements AppLayerEvent.

Unfortunately the parser registration cannot use these functions
directly as generic functions cannot be #[no_mangle]. So they
do need small extern "C" wrappers around them.

rust/src/applayer.rs

index 084e8d0bf9ca235e4770c1cf765e9387b1f07921..008610dec2f8cf3498a5e8e11f16ea52849dae97 100644 (file)
 //! Parser registration functions and common interface
 
 use std;
-use crate::core::{DetectEngineState,Flow,AppLayerEventType,AppLayerDecoderEvents,AppProto};
+use crate::core::{self,DetectEngineState,Flow,AppLayerEventType,AppLayerDecoderEvents,AppProto};
 use crate::filecontainer::FileContainer;
 use crate::applayer;
 use std::os::raw::{c_void,c_char,c_int};
 use crate::core::SC;
+use std::ffi::CStr;
 
 #[repr(C)]
 #[derive(Default, Debug,PartialEq)]
@@ -425,9 +426,61 @@ pub trait AppLayerEvent {
     /// Convert the enum variant to a C-style string (suffixed with \0).
     fn to_cstring(&self) -> &str;
 
-    /// Return the enum variant for the given name (as a CStr).
-    fn from_cstring(s: &std::ffi::CStr) -> Option<Self> where Self: std::marker::Sized;
+    /// Return the enum variant for the given name.
+    fn from_string(s: &str) -> Option<Self> where Self: std::marker::Sized;
 
     /// Return the ID value of the enum variant.
     fn as_i32(&self) -> i32;
 }
+
+/// Generic `get_info_info` implementation for enums implementing
+/// AppLayerEvent.
+///
+/// Normally usage of this function will be generated by
+/// derive(AppLayerEvent), for example:
+///
+/// #[derive(AppLayerEvent)]
+/// enum AppEvent {
+///     EventOne,
+///     EventTwo,
+/// }
+///
+/// get_event_info::<AppEvent>(...)
+#[inline(always)]
+pub fn get_event_info<T: AppLayerEvent>(
+    event_name: *const std::os::raw::c_char,
+    event_id: *mut std::os::raw::c_int,
+    event_type: *mut core::AppLayerEventType,
+) -> std::os::raw::c_int {
+    if event_name == std::ptr::null() {
+        return -1;
+    }
+
+    unsafe {
+        let event = match CStr::from_ptr(event_name).to_str().map(T::from_string) {
+            Ok(Some(event)) => event.as_i32(),
+            _ => -1,
+        };
+        *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
+        *event_id = event as std::os::raw::c_int;
+        return 0;
+    }
+}
+
+/// Generic `get_info_info_by_id` implementation for enums implementing
+/// AppLayerEvent.
+#[inline(always)]
+pub fn get_event_info_by_id<T: AppLayerEvent>(
+    event_id: std::os::raw::c_int,
+    event_name: *mut *const std::os::raw::c_char,
+    event_type: *mut core::AppLayerEventType,
+) -> i8 {
+    if let Some(e) = T::from_id(event_id as i32) {
+        unsafe {
+            *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char;
+            *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
+        }
+        return 0;
+    }
+    return -1;
+}