/src/suricata7/rust/src/log.rs
Line | Count | Source |
1 | | /* Copyright (C) 2017 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | //! Logging utility module. |
19 | | |
20 | | use std; |
21 | | use std::ffi::CString; |
22 | | use std::path::Path; |
23 | | |
24 | | use crate::core::*; |
25 | | |
26 | | #[derive(Debug)] |
27 | | #[repr(C)] |
28 | | pub enum Level { |
29 | | NotSet = -1, |
30 | | _None = 0, |
31 | | Error, |
32 | | Warning, |
33 | | Notice, |
34 | | Info, |
35 | | _Perf, |
36 | | Config, |
37 | | #[cfg(feature = "debug")] |
38 | | Debug, |
39 | | } |
40 | | |
41 | | pub static mut LEVEL: i32 = Level::NotSet as i32; |
42 | | |
43 | 73.4k | pub fn get_log_level() -> i32 { |
44 | | unsafe { |
45 | 73.4k | LEVEL |
46 | | } |
47 | 73.4k | } |
48 | | |
49 | 37 | pub fn log_set_level(level: i32) { |
50 | 37 | unsafe { |
51 | 37 | LEVEL = level; |
52 | 37 | } |
53 | 37 | } |
54 | | |
55 | | #[no_mangle] |
56 | 37 | pub extern "C" fn rs_log_set_level(level: i32) { |
57 | 37 | log_set_level(level); |
58 | 37 | } |
59 | | |
60 | 73.3k | fn basename(filename: &str) -> &str { |
61 | 73.3k | let path = Path::new(filename); |
62 | 73.3k | if let Some(os_str) = path.file_name() { |
63 | 73.3k | if let Some(basename) = os_str.to_str() { |
64 | 73.3k | return basename; |
65 | 0 | } |
66 | 0 | } |
67 | 0 | return filename; |
68 | 73.3k | } |
69 | | |
70 | 73.3k | pub fn sclog(level: Level, file: &str, line: u32, function: &str, |
71 | 73.3k | message: &str) |
72 | | { |
73 | 73.3k | let filename = basename(file); |
74 | 73.3k | let noext = &filename[0..filename.len() - 3]; |
75 | 73.3k | sc_log_message(level, |
76 | 73.3k | filename, |
77 | 73.3k | line, |
78 | 73.3k | function, |
79 | 73.3k | noext, |
80 | 73.3k | message); |
81 | 73.3k | } |
82 | | |
83 | | // This macro returns the function name. |
84 | | // |
85 | | // This macro has been borrowed from https://github.com/popzxc/stdext-rs, which |
86 | | // is released under the MIT license as there is currently no macro in Rust |
87 | | // to provide the function name. |
88 | | #[macro_export(local_inner_macros)] |
89 | | macro_rules!function { |
90 | | () => {{ |
91 | | // Okay, this is ugly, I get it. However, this is the best we can get on a stable rust. |
92 | 0 | fn __f() {}Unexecuted instantiation: <suricata::applayertemplate::template::TemplateState>::parse_request::__f Unexecuted instantiation: <suricata::applayertemplate::template::TemplateState>::parse_response::__f Unexecuted instantiation: <suricata::applayertemplate::template::TemplateState>::parse_response::__f Unexecuted instantiation: <suricata::applayertemplate::template::TemplateState>::parse_response::__f Unexecuted instantiation: suricata::applayertemplate::template::rs_template_register_parser::__f Unexecuted instantiation: suricata::applayertemplate::template::rs_template_register_parser::__f Unexecuted instantiation: suricata::applayertemplate::template::rs_template_register_parser::__f Unexecuted instantiation: suricata::nfs::nfs::rs_nfs_udp_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::__f Unexecuted instantiation: suricata::ssh::ssh::rs_ssh_register_parser::__f Unexecuted instantiation: suricata::asn1::parse_rules::rs_detect_asn1_parse::__f Unexecuted instantiation: suricata::asn1::parse_rules::rs_detect_asn1_parse::__f Unexecuted instantiation: suricata::mqtt::mqtt::rs_mqtt_register_parser::__f Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::__f Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::__f Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::__f Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::__f Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::__f Unexecuted instantiation: suricata::pgsql::pgsql::SCRegisterPgsqlParser::__f Unexecuted instantiation: suricata::pgsql::pgsql::SCRegisterPgsqlParser::__f Unexecuted instantiation: suricata::dcerpc::dcerpc::rs_dcerpc_register_parser::__f Unexecuted instantiation: suricata::dcerpc::dcerpc::rs_dcerpc_register_parser::__f Unexecuted instantiation: suricata::dcerpc::dcerpc::rs_dcerpc_register_parser::__f Unexecuted instantiation: suricata::detect::requires::parse_requires::__f Unexecuted instantiation: suricata::detect::requires::SCDetectRequiresStatusLog::__f Unexecuted instantiation: suricata::detect::requires::SCDetectRequiresStatusLog::__f Unexecuted instantiation: suricata::modbus::detect::parse_range::__f Unexecuted instantiation: suricata::modbus::detect::parse_range::__f Unexecuted instantiation: suricata::modbus::detect::parse_range::__f Unexecuted instantiation: suricata::modbus::detect::parse_access::__f Unexecuted instantiation: suricata::modbus::detect::parse_access::__f Unexecuted instantiation: suricata::modbus::detect::parse_access::__f Unexecuted instantiation: suricata::modbus::detect::parse_access::__f Unexecuted instantiation: suricata::modbus::detect::parse_access::__f Unexecuted instantiation: suricata::modbus::detect::parse_access::__f Unexecuted instantiation: suricata::modbus::detect::parse_access::__f Unexecuted instantiation: suricata::modbus::detect::parse_unit_id::__f Unexecuted instantiation: suricata::modbus::detect::parse_unit_id::__f Unexecuted instantiation: suricata::modbus::detect::parse_function::__f Unexecuted instantiation: suricata::modbus::detect::parse_function::__f Unexecuted instantiation: suricata::modbus::detect::parse_function::__f |
93 | 73.3k | fn type_name_of<T>(_: T) -> &'static str { |
94 | 73.3k | std::any::type_name::<T>() |
95 | 73.3k | } suricata::modbus::detect::parse_range::type_name_of::<suricata::modbus::detect::parse_range::__f> Line | Count | Source | 93 | 469 | fn type_name_of<T>(_: T) -> &'static str { | 94 | 469 | std::any::type_name::<T>() | 95 | 469 | } |
suricata::modbus::detect::parse_range::type_name_of::<suricata::modbus::detect::parse_range::__f> Line | Count | Source | 93 | 10 | fn type_name_of<T>(_: T) -> &'static str { | 94 | 10 | std::any::type_name::<T>() | 95 | 10 | } |
suricata::modbus::detect::parse_range::type_name_of::<suricata::modbus::detect::parse_range::__f> Line | Count | Source | 93 | 24 | fn type_name_of<T>(_: T) -> &'static str { | 94 | 24 | std::any::type_name::<T>() | 95 | 24 | } |
Unexecuted instantiation: suricata::modbus::detect::parse_access::type_name_of::<suricata::modbus::detect::parse_access::__f> Unexecuted instantiation: suricata::modbus::detect::parse_access::type_name_of::<suricata::modbus::detect::parse_access::__f> Unexecuted instantiation: suricata::modbus::detect::parse_access::type_name_of::<suricata::modbus::detect::parse_access::__f> Unexecuted instantiation: suricata::modbus::detect::parse_access::type_name_of::<suricata::modbus::detect::parse_access::__f> Unexecuted instantiation: suricata::modbus::detect::parse_access::type_name_of::<suricata::modbus::detect::parse_access::__f> Unexecuted instantiation: suricata::modbus::detect::parse_access::type_name_of::<suricata::modbus::detect::parse_access::__f> Unexecuted instantiation: suricata::modbus::detect::parse_access::type_name_of::<suricata::modbus::detect::parse_access::__f> suricata::modbus::detect::parse_unit_id::type_name_of::<suricata::modbus::detect::parse_unit_id::__f> Line | Count | Source | 93 | 1.97k | fn type_name_of<T>(_: T) -> &'static str { | 94 | 1.97k | std::any::type_name::<T>() | 95 | 1.97k | } |
Unexecuted instantiation: suricata::modbus::detect::parse_unit_id::type_name_of::<suricata::modbus::detect::parse_unit_id::__f> suricata::modbus::detect::parse_function::type_name_of::<suricata::modbus::detect::parse_function::__f> Line | Count | Source | 93 | 455 | fn type_name_of<T>(_: T) -> &'static str { | 94 | 455 | std::any::type_name::<T>() | 95 | 455 | } |
suricata::modbus::detect::parse_function::type_name_of::<suricata::modbus::detect::parse_function::__f> Line | Count | Source | 93 | 1.62k | fn type_name_of<T>(_: T) -> &'static str { | 94 | 1.62k | std::any::type_name::<T>() | 95 | 1.62k | } |
Unexecuted instantiation: suricata::modbus::detect::parse_function::type_name_of::<suricata::modbus::detect::parse_function::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::smb::smb::rs_smb_register_parser::type_name_of::<suricata::smb::smb::rs_smb_register_parser::__f> Unexecuted instantiation: suricata::ssh::ssh::rs_ssh_register_parser::type_name_of::<suricata::ssh::ssh::rs_ssh_register_parser::__f> Unexecuted instantiation: suricata::mqtt::mqtt::rs_mqtt_register_parser::type_name_of::<suricata::mqtt::mqtt::rs_mqtt_register_parser::__f> Unexecuted instantiation: suricata::asn1::parse_rules::rs_detect_asn1_parse::type_name_of::<suricata::asn1::parse_rules::rs_detect_asn1_parse::__f> suricata::asn1::parse_rules::rs_detect_asn1_parse::type_name_of::<suricata::asn1::parse_rules::rs_detect_asn1_parse::__f> Line | Count | Source | 93 | 1.20k | fn type_name_of<T>(_: T) -> &'static str { | 94 | 1.20k | std::any::type_name::<T>() | 95 | 1.20k | } |
suricata::detect::requires::parse_requires::type_name_of::<suricata::detect::requires::parse_requires::__f> Line | Count | Source | 93 | 39.5k | fn type_name_of<T>(_: T) -> &'static str { | 94 | 39.5k | std::any::type_name::<T>() | 95 | 39.5k | } |
suricata::detect::requires::SCDetectRequiresStatusLog::type_name_of::<suricata::detect::requires::SCDetectRequiresStatusLog::__f> Line | Count | Source | 93 | 83 | fn type_name_of<T>(_: T) -> &'static str { | 94 | 83 | std::any::type_name::<T>() | 95 | 83 | } |
suricata::detect::requires::SCDetectRequiresStatusLog::type_name_of::<suricata::detect::requires::SCDetectRequiresStatusLog::__f> Line | Count | Source | 93 | 37 | fn type_name_of<T>(_: T) -> &'static str { | 94 | 37 | std::any::type_name::<T>() | 95 | 37 | } |
<suricata::applayertemplate::template::TemplateState>::parse_request::type_name_of::<<suricata::applayertemplate::template::TemplateState>::parse_request::__f> Line | Count | Source | 93 | 9.52k | fn type_name_of<T>(_: T) -> &'static str { | 94 | 9.52k | std::any::type_name::<T>() | 95 | 9.52k | } |
<suricata::applayertemplate::template::TemplateState>::parse_response::type_name_of::<<suricata::applayertemplate::template::TemplateState>::parse_response::__f> Line | Count | Source | 93 | 6.10k | fn type_name_of<T>(_: T) -> &'static str { | 94 | 6.10k | std::any::type_name::<T>() | 95 | 6.10k | } |
<suricata::applayertemplate::template::TemplateState>::parse_response::type_name_of::<<suricata::applayertemplate::template::TemplateState>::parse_response::__f> Line | Count | Source | 93 | 6.10k | fn type_name_of<T>(_: T) -> &'static str { | 94 | 6.10k | std::any::type_name::<T>() | 95 | 6.10k | } |
<suricata::applayertemplate::template::TemplateState>::parse_response::type_name_of::<<suricata::applayertemplate::template::TemplateState>::parse_response::__f> Line | Count | Source | 93 | 6.10k | fn type_name_of<T>(_: T) -> &'static str { | 94 | 6.10k | std::any::type_name::<T>() | 95 | 6.10k | } |
Unexecuted instantiation: suricata::applayertemplate::template::rs_template_register_parser::type_name_of::<suricata::applayertemplate::template::rs_template_register_parser::__f> Unexecuted instantiation: suricata::applayertemplate::template::rs_template_register_parser::type_name_of::<suricata::applayertemplate::template::rs_template_register_parser::__f> suricata::applayertemplate::template::rs_template_register_parser::type_name_of::<suricata::applayertemplate::template::rs_template_register_parser::__f> Line | Count | Source | 93 | 33 | fn type_name_of<T>(_: T) -> &'static str { | 94 | 33 | std::any::type_name::<T>() | 95 | 33 | } |
Unexecuted instantiation: suricata::nfs::nfs::rs_nfs_udp_register_parser::type_name_of::<suricata::nfs::nfs::rs_nfs_udp_register_parser::__f> Unexecuted instantiation: suricata::pgsql::pgsql::SCRegisterPgsqlParser::type_name_of::<suricata::pgsql::pgsql::SCRegisterPgsqlParser::__f> Unexecuted instantiation: suricata::pgsql::pgsql::SCRegisterPgsqlParser::type_name_of::<suricata::pgsql::pgsql::SCRegisterPgsqlParser::__f> Unexecuted instantiation: suricata::dcerpc::dcerpc::rs_dcerpc_register_parser::type_name_of::<suricata::dcerpc::dcerpc::rs_dcerpc_register_parser::__f> Unexecuted instantiation: suricata::dcerpc::dcerpc::rs_dcerpc_register_parser::type_name_of::<suricata::dcerpc::dcerpc::rs_dcerpc_register_parser::__f> Unexecuted instantiation: suricata::dcerpc::dcerpc::rs_dcerpc_register_parser::type_name_of::<suricata::dcerpc::dcerpc::rs_dcerpc_register_parser::__f> Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::type_name_of::<suricata::http2::http2::rs_http2_register_parser::__f> Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::type_name_of::<suricata::http2::http2::rs_http2_register_parser::__f> Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::type_name_of::<suricata::http2::http2::rs_http2_register_parser::__f> Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::type_name_of::<suricata::http2::http2::rs_http2_register_parser::__f> Unexecuted instantiation: suricata::http2::http2::rs_http2_register_parser::type_name_of::<suricata::http2::http2::rs_http2_register_parser::__f> |
96 | | let name = type_name_of(__f); |
97 | | &name[..name.len() - 5] |
98 | | }} |
99 | | } |
100 | | |
101 | | #[macro_export] |
102 | | macro_rules!do_log { |
103 | | ($level:expr, $($arg:tt)*) => { |
104 | | if $crate::log::get_log_level() >= $level as i32 { |
105 | | $crate::log::sclog($level, file!(), line!(), $crate::function!(), |
106 | | &(format!($($arg)*))); |
107 | | } |
108 | | } |
109 | | } |
110 | | |
111 | | #[macro_export] |
112 | | macro_rules!SCLogError { |
113 | | ($($arg:tt)*) => { |
114 | | $crate::do_log!($crate::log::Level::Error, $($arg)*); |
115 | | }; |
116 | | } |
117 | | |
118 | | #[macro_export] |
119 | | macro_rules!SCLogWarning { |
120 | | ($($arg:tt)*) => { |
121 | | $crate::do_log!($crate::log::Level::Warning, $($arg)*); |
122 | | }; |
123 | | } |
124 | | |
125 | | #[macro_export] |
126 | | macro_rules!SCLogNotice { |
127 | | ($($arg:tt)*) => { |
128 | | $crate::do_log!($crate::log::Level::Notice, $($arg)*); |
129 | | } |
130 | | } |
131 | | |
132 | | #[macro_export] |
133 | | macro_rules!SCLogInfo { |
134 | | ($($arg:tt)*) => { |
135 | | $crate::do_log!($crate::log::Level::Info, $($arg)*); |
136 | | } |
137 | | } |
138 | | |
139 | | #[macro_export] |
140 | | macro_rules!SCLogPerf { |
141 | | ($($arg:tt)*) => { |
142 | | $crate::do_log!($crate::log::Level::Perf, $($arg)*); |
143 | | } |
144 | | } |
145 | | |
146 | | #[macro_export] |
147 | | macro_rules!SCLogConfig { |
148 | | ($($arg:tt)*) => { |
149 | | $crate::do_log!($crate::log::Level::Config, $($arg)*); |
150 | | } |
151 | | } |
152 | | |
153 | | // Debug mode: call C SCLogDebug |
154 | | #[cfg(feature = "debug")] |
155 | | #[macro_export] |
156 | | macro_rules!SCLogDebug { |
157 | | ($($arg:tt)*) => { |
158 | | do_log!($crate::log::Level::Debug, $($arg)*); |
159 | | } |
160 | | } |
161 | | |
162 | | // SCLogDebug variation to use when not compiled with debug support. |
163 | | // |
164 | | // This macro will only use the parameters passed to prevent warnings |
165 | | // about unused variables, but is otherwise the equivalent to a no-op. |
166 | | #[cfg(not(feature = "debug"))] |
167 | | #[macro_export] |
168 | | macro_rules!SCLogDebug { |
169 | | ($($arg:tt)*) => () |
170 | | } |
171 | | |
172 | | /// SCLogMessage wrapper. If the Suricata C context is not registered |
173 | | /// a more basic log format will be used (for example, when running |
174 | | /// Rust unit tests). |
175 | 73.3k | pub fn sc_log_message(level: Level, |
176 | 73.3k | filename: &str, |
177 | 73.3k | line: std::os::raw::c_uint, |
178 | 73.3k | function: &str, |
179 | 73.3k | module: &str, |
180 | 73.3k | message: &str) -> std::os::raw::c_int |
181 | | { |
182 | | unsafe { |
183 | 73.3k | if let Some(c) = SC { |
184 | 73.3k | return (c.SCLogMessage)( |
185 | 73.3k | level as i32, |
186 | 73.3k | to_safe_cstring(filename).as_ptr(), |
187 | 73.3k | line, |
188 | 73.3k | to_safe_cstring(function).as_ptr(), |
189 | 73.3k | to_safe_cstring(module).as_ptr(), |
190 | 73.3k | to_safe_cstring(message).as_ptr()); |
191 | 0 | } |
192 | | } |
193 | | |
194 | | // Fall back if the Suricata C context is not registered which is |
195 | | // the case when Rust unit tests are running. |
196 | | // |
197 | | // We don't log the time right now as I don't think it can be done |
198 | | // with Rust 1.7.0 without using an external crate. With Rust |
199 | | // 1.8.0 and newer we can unix UNIX_EPOCH.elapsed() to get the |
200 | | // unix time. |
201 | 0 | println!("{}:{} <{:?}> -- {}", filename, line, level, message); |
202 | 0 | return 0; |
203 | 73.3k | } |
204 | | |
205 | | // Convert a &str into a CString by first stripping NUL bytes. |
206 | 293k | fn to_safe_cstring(val: &str) -> CString { |
207 | 293k | let mut safe = Vec::with_capacity(val.len()); |
208 | 8.26M | for c in val.as_bytes() { |
209 | 8.26M | if *c != 0 { |
210 | 8.26M | safe.push(*c); |
211 | 8.26M | } |
212 | | } |
213 | 293k | match CString::new(safe) { |
214 | 293k | Ok(cstr) => cstr, |
215 | | _ => { |
216 | 0 | CString::new("<failed to encode string>").unwrap() |
217 | | } |
218 | | } |
219 | 293k | } |