From: Jason Ish Date: Fri, 17 Jan 2025 18:06:53 +0000 (-0600) Subject: rust/log: move rust log and debug utils to debug module X-Git-Tag: suricata-8.0.0-beta1~550 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2bcc66da5826fa0e6e074a756754b295e5ac4da2;p=thirdparty%2Fsuricata.git rust/log: move rust log and debug utils to debug module Move Rust logging, and debug_validation to a debug module to mirrow the C side. --- diff --git a/rust/src/common.rs b/rust/src/common.rs index c874cc58b8..aa7741f5e1 100644 --- a/rust/src/common.rs +++ b/rust/src/common.rs @@ -62,39 +62,6 @@ pub mod nom7 { } } -#[cfg(not(feature = "debug-validate"))] -#[macro_export] -macro_rules! debug_validate_bug_on ( - ($item:expr) => {}; -); - -#[cfg(feature = "debug-validate")] -#[macro_export] -macro_rules! debug_validate_bug_on ( - ($item:expr) => { - if $item { - panic!("Condition check failed"); - } - }; -); - -#[cfg(not(feature = "debug-validate"))] -#[macro_export] -macro_rules! debug_validate_fail ( - ($msg:expr) => {}; -); - -#[cfg(feature = "debug-validate")] -#[macro_export] -macro_rules! debug_validate_fail ( - ($msg:expr) => { - // Wrap in a conditional to prevent unreachable code warning in caller. - if true { - panic!($msg); - } - }; -); - /// Convert a String to C-compatible string /// /// This function will consume the provided data and use the underlying bytes to construct a new diff --git a/rust/src/core.rs b/rust/src/core.rs index 387d2b1524..7e1094a39e 100644 --- a/rust/src/core.rs +++ b/rust/src/core.rs @@ -176,7 +176,6 @@ pub struct SuricataFileContext { /// cbindgen:ignore extern { pub fn SCGetContext() -> &'static mut SuricataContext; - pub fn SCLogGetLogLevel() -> i32; } pub static mut SC: Option<&'static SuricataContext> = None; diff --git a/rust/src/dcerpc/dcerpc.rs b/rust/src/dcerpc/dcerpc.rs index 433dc4b5bf..c8c377a372 100644 --- a/rust/src/dcerpc/dcerpc.rs +++ b/rust/src/dcerpc/dcerpc.rs @@ -1388,7 +1388,6 @@ pub unsafe extern "C" fn rs_dcerpc_register_parser() { #[cfg(test)] mod tests { use crate::applayer::AppLayerResult; - use crate::core::*; use crate::dcerpc::dcerpc::DCERPCState; use crate::direction::Direction; use std::cmp; diff --git a/rust/src/log.rs b/rust/src/debug.rs similarity index 61% rename from rust/src/log.rs rename to rust/src/debug.rs index 7bf0be8a97..caeecff93a 100644 --- a/rust/src/log.rs +++ b/rust/src/debug.rs @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Open Information Security Foundation +/* Copyright (C) 2017-2025 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 @@ -15,13 +15,16 @@ * 02110-1301, USA. */ -//! Logging utility module. +//! Logging and debug utilities, like util-debug.c. -use std; -use std::ffi::CString; -use std::path::Path; +use std::{ffi::CString, path::Path}; -use crate::core::*; +use crate::core::SC; + +/// cbindgen:ignore +extern { + pub fn SCLogGetLogLevel() -> i32; +} #[derive(Debug)] #[repr(C)] @@ -40,21 +43,13 @@ pub enum Level { pub static mut LEVEL: i32 = Level::NotSet as i32; -pub fn get_log_level() -> i32 { - unsafe { - LEVEL - } -} - -pub fn log_set_level(level: i32) { - unsafe { - LEVEL = level; - } -} - +/// Set the Rust context's idea of the log level. +/// +/// This will be called during Suricata initialization with the +/// runtime log level. #[no_mangle] -pub extern "C" fn rs_log_set_level(level: i32) { - log_set_level(level); +pub unsafe extern "C" fn SCSetRustLogLevel(level: i32) { + LEVEL = level; } fn basename(filename: &str) -> &str { @@ -67,17 +62,55 @@ fn basename(filename: &str) -> &str { return filename; } -pub fn sclog(level: Level, file: &str, line: u32, function: &str, - message: &str) -{ +pub fn sclog(level: Level, file: &str, line: u32, function: &str, message: &str) { let filename = basename(file); let noext = &filename[0..filename.len() - 3]; - sc_log_message(level, - filename, - line, - function, - noext, - message); + sc_log_message(level, filename, line, function, noext, message); +} + +/// SCLogMessage wrapper. If the Suricata C context is not registered +/// a more basic log format will be used (for example, when running +/// Rust unit tests). +pub fn sc_log_message( + level: Level, filename: &str, line: std::os::raw::c_uint, function: &str, module: &str, + message: &str, +) -> std::os::raw::c_int { + unsafe { + if let Some(c) = SC { + return (c.SCLogMessage)( + level as i32, + to_safe_cstring(filename).as_ptr(), + line, + to_safe_cstring(function).as_ptr(), + to_safe_cstring(module).as_ptr(), + to_safe_cstring(message).as_ptr(), + ); + } + } + + // Fall back if the Suricata C context is not registered which is + // the case when Rust unit tests are running. + // + // We don't log the time right now as I don't think it can be done + // with Rust 1.7.0 without using an external crate. With Rust + // 1.8.0 and newer we can unix UNIX_EPOCH.elapsed() to get the + // unix time. + println!("{}:{} <{:?}> -- {}", filename, line, level, message); + return 0; +} + +// Convert a &str into a CString by first stripping NUL bytes. +fn to_safe_cstring(val: &str) -> CString { + let mut safe = Vec::with_capacity(val.len()); + for c in val.as_bytes() { + if *c != 0 { + safe.push(*c); + } + } + match CString::new(safe) { + Ok(cstr) => cstr, + _ => CString::new("").unwrap(), + } } // This macro returns the function name. @@ -86,23 +119,24 @@ pub fn sclog(level: Level, file: &str, line: u32, function: &str, // is released under the MIT license as there is currently no macro in Rust // to provide the function name. #[macro_export(local_inner_macros)] -macro_rules!function { +macro_rules! function { () => {{ - // Okay, this is ugly, I get it. However, this is the best we can get on a stable rust. - fn __f() {} - fn type_name_of(_: T) -> &'static str { - std::any::type_name::() - } - let name = type_name_of(__f); - &name[..name.len() - 5] - }} + // Okay, this is ugly, I get it. However, this is the best we can get on a stable rust. + fn __f() {} + fn type_name_of(_: T) -> &'static str { + std::any::type_name::() + } + let name = type_name_of(__f); + &name[..name.len() - 5] + }}; } #[macro_export] macro_rules!do_log { ($level:expr, $($arg:tt)*) => { - if $crate::log::get_log_level() >= $level as i32 { - $crate::log::sclog($level, file!(), line!(), $crate::function!(), + #[allow(unused_unsafe)] + if unsafe { $crate::debug::LEVEL } >= $level as i32 { + $crate::debug::sclog($level, file!(), line!(), $crate::function!(), &(format!($($arg)*))); } } @@ -111,42 +145,42 @@ macro_rules!do_log { #[macro_export] macro_rules!SCLogError { ($($arg:tt)*) => { - $crate::do_log!($crate::log::Level::Error, $($arg)*); + $crate::do_log!($crate::debug::Level::Error, $($arg)*); }; } #[macro_export] macro_rules!SCLogWarning { ($($arg:tt)*) => { - $crate::do_log!($crate::log::Level::Warning, $($arg)*); + $crate::do_log!($crate::debug::Level::Warning, $($arg)*); }; } #[macro_export] macro_rules!SCLogNotice { ($($arg:tt)*) => { - $crate::do_log!($crate::log::Level::Notice, $($arg)*); + $crate::do_log!($crate::debug::Level::Notice, $($arg)*); } } #[macro_export] macro_rules!SCLogInfo { ($($arg:tt)*) => { - $crate::do_log!($crate::log::Level::Info, $($arg)*); + $crate::do_log!($crate::debug::Level::Info, $($arg)*); } } #[macro_export] macro_rules!SCLogPerf { ($($arg:tt)*) => { - $crate::do_log!($crate::log::Level::Perf, $($arg)*); + $crate::do_log!($crate::debug::Level::Perf, $($arg)*); } } #[macro_export] macro_rules!SCLogConfig { ($($arg:tt)*) => { - $crate::do_log!($crate::log::Level::Config, $($arg)*); + $crate::do_log!($crate::debug::Level::Config, $($arg)*); } } @@ -155,7 +189,7 @@ macro_rules!SCLogConfig { #[macro_export] macro_rules!SCLogDebug { ($($arg:tt)*) => { - do_log!($crate::log::Level::Debug, $($arg)*); + do_log!($crate::debug::Level::Debug, $($arg)*); } } @@ -165,55 +199,40 @@ macro_rules!SCLogDebug { // about unused variables, but is otherwise the equivalent to a no-op. #[cfg(not(feature = "debug"))] #[macro_export] -macro_rules!SCLogDebug { - ($($arg:tt)*) => () +macro_rules! SCLogDebug { + ($($arg:tt)*) => {}; } -/// SCLogMessage wrapper. If the Suricata C context is not registered -/// a more basic log format will be used (for example, when running -/// Rust unit tests). -pub fn sc_log_message(level: Level, - filename: &str, - line: std::os::raw::c_uint, - function: &str, - module: &str, - message: &str) -> std::os::raw::c_int -{ - unsafe { - if let Some(c) = SC { - return (c.SCLogMessage)( - level as i32, - to_safe_cstring(filename).as_ptr(), - line, - to_safe_cstring(function).as_ptr(), - to_safe_cstring(module).as_ptr(), - to_safe_cstring(message).as_ptr()); - } - } +#[cfg(not(feature = "debug-validate"))] +#[macro_export] +macro_rules! debug_validate_bug_on ( + ($item:expr) => {}; +); - // Fall back if the Suricata C context is not registered which is - // the case when Rust unit tests are running. - // - // We don't log the time right now as I don't think it can be done - // with Rust 1.7.0 without using an external crate. With Rust - // 1.8.0 and newer we can unix UNIX_EPOCH.elapsed() to get the - // unix time. - println!("{}:{} <{:?}> -- {}", filename, line, level, message); - return 0; -} -// Convert a &str into a CString by first stripping NUL bytes. -fn to_safe_cstring(val: &str) -> CString { - let mut safe = Vec::with_capacity(val.len()); - for c in val.as_bytes() { - if *c != 0 { - safe.push(*c); - } +#[cfg(feature = "debug-validate")] +#[macro_export] +macro_rules! debug_validate_bug_on ( + ($item:expr) => { + if $item { + panic!("Condition check failed"); } - match CString::new(safe) { - Ok(cstr) => cstr, - _ => { - CString::new("").unwrap() - } + }; +); + +#[cfg(not(feature = "debug-validate"))] +#[macro_export] +macro_rules! debug_validate_fail ( + ($msg:expr) => {}; +); + +#[cfg(feature = "debug-validate")] +#[macro_export] +macro_rules! debug_validate_fail ( + ($msg:expr) => { + // Wrap in a conditional to prevent unreachable code warning in caller. + if true { + panic!($msg); } -} + }; +); diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 855ee11e29..f28e4c249a 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -79,13 +79,12 @@ extern crate ldap_parser; #[macro_use] extern crate suricata_derive; -#[macro_use] -pub mod log; - #[macro_use] pub mod core; #[macro_use] +pub(crate) mod debug; + pub mod common; pub mod conf; pub mod jsonbuilder; diff --git a/rust/src/plugin.rs b/rust/src/plugin.rs index ad214aaa47..7f37586408 100644 --- a/rust/src/plugin.rs +++ b/rust/src/plugin.rs @@ -22,7 +22,6 @@ pub fn init() { let context = super::core::SCGetContext(); super::core::init_ffi(context); - let level = super::core::SCLogGetLogLevel(); - super::log::log_set_level(level); + super::debug::SCSetRustLogLevel(super::debug::SCLogGetLogLevel()); } } diff --git a/src/util-debug.c b/src/util-debug.c index f2a7b2dd21..56258a034f 100644 --- a/src/util-debug.c +++ b/src/util-debug.c @@ -1414,7 +1414,7 @@ void SCLogInitLogModule(SCLogInitData *sc_lid) //SCOutputPrint(sc_did->startup_message); - rs_log_set_level(sc_log_global_log_level); + SCSetRustLogLevel(sc_log_global_log_level); } void SCLogLoadConfig(int daemon, int verbose, uint32_t userid, uint32_t groupid)