From: Jason Ish Date: Wed, 18 Nov 2020 17:57:22 +0000 (-0600) Subject: rust/applayer: provide generic event info functions X-Git-Tag: suricata-7.0.0-beta1~1470 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0fa7b5c2a2204c6d8ee29489c7b08ff7f1fe68f5;p=thirdparty%2Fsuricata.git rust/applayer: provide generic event info functions 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. --- diff --git a/rust/src/applayer.rs b/rust/src/applayer.rs index 084e8d0bf9..008610dec2 100644 --- a/rust/src/applayer.rs +++ b/rust/src/applayer.rs @@ -18,11 +18,12 @@ //! 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 where Self: std::marker::Sized; + /// Return the enum variant for the given name. + fn from_string(s: &str) -> Option 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::(...) +#[inline(always)] +pub fn get_event_info( + 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( + 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; +}