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.
pull/12424/head
Jason Ish 2 years ago committed by Victor Julien
parent f62be374ea
commit 2bcc66da58

@ -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

@ -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;

@ -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;

@ -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("<failed to encode string>").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>(_: T) -> &'static str {
std::any::type_name::<T>()
}
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>(_: T) -> &'static str {
std::any::type_name::<T>()
}
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("<failed to encode string>").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);
}
}
};
);

@ -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;

@ -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());
}
}

@ -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)

Loading…
Cancel
Save