Skip to content

Commit f9d8284

Browse files
committed
wip
1 parent 278dc24 commit f9d8284

22 files changed

+929
-1
lines changed

rust/Cargo.toml.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2021"
77
rust-version = "1.67.1"
88

99
[workspace]
10-
members = [".", "./derive"]
10+
members = [".", "./derive", "./config"]
1111

1212
[lib]
1313
crate-type = ["staticlib", "rlib"]
@@ -68,6 +68,7 @@ hex = "~0.4.3"
6868
time = "~0.3.36"
6969

7070
suricata-derive = { path = "./derive", version = "@PACKAGE_VERSION@" }
71+
suricata-config = { path = "./config", version = "0.1.0" }
7172

7273
suricata-lua-sys = { version = "0.1.0-alpha.3" }
7374

rust/Makefile.am

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ EXTRA_DIST = src derive \
22
.cargo/config.toml.in \
33
cbindgen.toml \
44
dist/rust-bindings.h \
5+
dist/rust-config.h \
56
vendor \
67
Cargo.toml Cargo.lock \
78
derive/Cargo.toml
@@ -60,6 +61,7 @@ endif
6061
$(RUST_SURICATA_LIBDIR)/${RUST_SURICATA_LIBNAME}; \
6162
fi
6263
$(MAKE) gen/rust-bindings.h
64+
rm -f gen/rust-config.h && $(MAKE) gen/rust-config.h
6365

6466
install-library:
6567
$(MKDIR_P) "$(DESTDIR)$(libdir)"
@@ -88,6 +90,9 @@ gen/rust-bindings.h: $(RUST_SURICATA_LIB)
8890
cd $(abs_top_srcdir)/rust && \
8991
cbindgen --config $(abs_top_srcdir)/rust/cbindgen.toml \
9092
--quiet --verify --output $(abs_top_builddir)/rust/gen/rust-bindings.h || true
93+
gen/rust-config.h: $(RUST_SURICATA_LIB)
94+
cbindgen --config $(abs_top_srcdir)/rust/config/cbindgen.toml \
95+
--quiet --verify --output $(abs_top_builddir)/rust/$@ config || true
9196
else
9297
gen/rust-bindings.h:
9398
endif

rust/config/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!/Cargo.toml

rust/config/Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "suricata-config"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# Saphyr requires 1.70.0
7+
rust-version = "1.70.0"
8+
9+
[dependencies]
10+
# Need to keep hashlink's version in check with saphyr.
11+
hashlink = "0.8.4"
12+
lazy_static = "1.4.0"
13+
14+
saphyr = { git = "https://github.com/saphyr-rs/saphyr" }
15+
saphyr-parser = { git = "https://github.com/saphyr-rs/saphyr" }

rust/config/cbindgen.toml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
language = "C"
2+
3+
4+
header = """/* Copyright (C) 2024 Open Information Security Foundation
5+
*
6+
* You can copy, redistribute or modify this Program under the terms of
7+
* the GNU General Public License version 2 as published by the Free
8+
* Software Foundation.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* version 2 along with this program; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18+
* 02110-1301, USA.
19+
*/"""
20+
21+
include_guard = "SURICATA_RUST_CONFIG_H"
22+
23+
autogen_warning = "/* DO NOT EDIT This file is autogenerated by cbindgen. Don't modify this manually. */"
24+
25+
include_version = true
26+
27+
includes = []
28+
29+
# Cbindgen doesn't appear to create structs for types from other
30+
# crates, so add an opaque definition of the YAML type here.
31+
after_includes = """typedef struct Yaml Yaml;"""
32+
33+
line_length = 80
34+
35+
tab_width = 4
36+
37+
documentation_style = "doxy"
38+
39+
[export]
40+
include = []
41+
42+
exclude = []
43+
44+
item_types = ["enums","structs","opaque","functions","constants"]
45+
46+
[export.rename]
47+
48+
renaming_overrides_prefixing = "true"
49+
50+
[enum]
51+
rename_variants = "ScreamingSnakeCase"
52+
prefix_with_name = true
53+
54+
[parse]
55+
exclude = ["libc"]
56+
57+
[parse.expand]
58+
features = ["cbindgen"]

rust/config/src/bin/loader.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-FileCopyrightText: Copyright (C) 2024 Open Information Security Foundation
2+
// SPDX-License-Identifier: MIT
3+
4+
use saphyr::Yaml;
5+
6+
fn main() {
7+
let filename = std::env::args().nth(1).expect("No filename given");
8+
let config = suricata_config::load_from_file(filename).unwrap();
9+
dump_yaml(&config, ".");
10+
}
11+
12+
fn dump_yaml(value: &Yaml, sep: &str) {
13+
let mut stack: Vec<(Vec<String>, &Yaml)> = vec![(vec![], value)];
14+
while let Some((prefix, node)) = stack.pop() {
15+
match node {
16+
Yaml::Real(value) => {
17+
println!("{} = {}", prefix.join(sep), value);
18+
}
19+
Yaml::Integer(value) => {
20+
println!("{} = {}", prefix.join(sep), value);
21+
}
22+
Yaml::String(value) => {
23+
println!("{} = {}", prefix.join(sep), value);
24+
}
25+
Yaml::Boolean(value) => {
26+
println!("{} = {}", prefix.join(sep), value);
27+
}
28+
Yaml::Array(array) => {
29+
let mut tmp = vec![];
30+
for (i, v) in array.iter().enumerate() {
31+
let mut prefix = prefix.clone();
32+
prefix.push(format!("{}", i));
33+
tmp.push((prefix, v));
34+
}
35+
tmp.reverse();
36+
stack.extend(tmp);
37+
}
38+
Yaml::Hash(hash) => {
39+
for (key, v) in hash.iter().rev() {
40+
let mut prefix = prefix.clone();
41+
prefix.push(key.as_str().unwrap().to_string());
42+
stack.push((prefix, v));
43+
}
44+
}
45+
Yaml::Null => {
46+
println!("{} = ~", prefix.join(sep));
47+
}
48+
Yaml::Alias(_) => todo!(),
49+
Yaml::BadValue => todo!(),
50+
}
51+
}
52+
}

rust/config/src/ffi.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// SPDX-FileCopyrightText: Copyright (C) 2024 Open Information Security Foundation
2+
// SPDX-License-Identifier: MIT
3+
4+
use std::{
5+
cell::RefCell,
6+
collections::HashMap,
7+
ffi::{CStr, CString},
8+
os::raw::c_char,
9+
sync::{Mutex, RwLock},
10+
};
11+
12+
use lazy_static::lazy_static;
13+
use saphyr::{Hash, Yaml};
14+
15+
thread_local! {
16+
static LAST_ERR: RefCell<Option<CString>> = const { RefCell::new(None) };
17+
}
18+
19+
lazy_static! {
20+
#[no_mangle]
21+
static ref GLOBAL: RwLock<Yaml> = RwLock::new(Yaml::Hash(Hash::new()));
22+
static ref CSTRINGS: Mutex<HashMap<String, CString>> = Mutex::new(HashMap::new());
23+
}
24+
25+
//pub struct SuriConfigYamlHashIter(linked_hash_map::Iter<'static, Yaml, Yaml>);
26+
27+
// Converts a Rust &str to CString, store it in CSTRINGS and return a *mut c_char.
28+
fn get_cstring(s: &str) -> Result<*const c_char, Box<dyn std::error::Error>> {
29+
let cstring = CString::new(s)?;
30+
let mut cstrings = CSTRINGS.lock().unwrap();
31+
cstrings.insert(s.to_string(), cstring);
32+
let s = cstrings.get(s).unwrap();
33+
Ok(s.as_ptr())
34+
}
35+
36+
#[no_mangle]
37+
pub unsafe extern "C" fn SuriConfigSetGlobal(yaml: *mut Yaml) {
38+
let yaml = Box::from_raw(yaml);
39+
let mut global = GLOBAL.write().unwrap();
40+
*global = *yaml;
41+
}
42+
43+
#[no_mangle]
44+
pub unsafe extern "C" fn SuriConfigLoadFromFile(filename: *const c_char) -> *mut Yaml {
45+
unsafe fn load_from_file(filename: *const c_char) -> Result<Yaml, Box<dyn std::error::Error>> {
46+
let filename = CStr::from_ptr(filename).to_str()?;
47+
crate::load_from_file(filename)
48+
}
49+
50+
match load_from_file(filename) {
51+
Ok(yaml) => Box::into_raw(Box::new(yaml)),
52+
Err(err) => {
53+
let err = CString::new(format!("{:?}", err)).unwrap();
54+
LAST_ERR.with(|last_err|{
55+
*last_err.borrow_mut() = Some(err);
56+
});
57+
std::ptr::null_mut()
58+
}
59+
}
60+
}
61+
62+
#[no_mangle]
63+
pub unsafe extern "C" fn SuriConfigLastErr() -> *const c_char {
64+
LAST_ERR.with(|last_err| {
65+
let last_err = last_err.borrow_mut();
66+
if let Some(err) = last_err.as_ref() {
67+
err.as_ptr()
68+
} else {
69+
std::ptr::null()
70+
}
71+
})
72+
}
73+
74+
#[no_mangle]
75+
pub unsafe extern "C" fn SuriConfigFree(yaml: *mut Yaml) {
76+
std::mem::drop(Box::from_raw(yaml));
77+
}
78+
79+
#[no_mangle]
80+
pub unsafe extern "C" fn SuriConfGet(name: *const c_char, vptr: *mut *const c_char) -> bool {
81+
pub unsafe fn conf_get(
82+
name: *const c_char, vptr: *mut *const c_char,
83+
) -> Result<(), Box<dyn std::error::Error>> {
84+
let name = CStr::from_ptr(name).to_str()?;
85+
let global = GLOBAL.read().unwrap();
86+
if let Some(node) = crate::get(&global, name) {
87+
if let Some(display) = crate::display(node) {
88+
*vptr = get_cstring(&display)?;
89+
}
90+
}
91+
Ok(())
92+
}
93+
94+
conf_get(name, vptr).is_ok()
95+
}

rust/config/src/file.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-FileCopyrightText: Copyright (C) 2024 Open Information Security Foundation
2+
// SPDX-License-Identifier: MIT
3+
4+
use std::io::Read;
5+
6+
/// A character iterator of a file to satisfy the YAML parser that only takes a char
7+
/// iterator. We could read the whole file into a string, but that could cause issues with
8+
/// very large files that may be passed by accident.
9+
pub struct FileCharIterator {
10+
file: std::fs::File,
11+
}
12+
13+
impl FileCharIterator {
14+
pub fn new(file: std::fs::File) -> Self {
15+
Self { file }
16+
}
17+
18+
fn next_char(&mut self) -> Option<char> {
19+
let mut buf: Vec<u8> = Vec::new();
20+
loop {
21+
let mut byte = [0; 1];
22+
match self.file.read(&mut byte) {
23+
Ok(n) => {
24+
if n == 0 {
25+
return None;
26+
}
27+
}
28+
Err(_) => {
29+
return None;
30+
}
31+
}
32+
buf.push(byte[0]);
33+
match String::from_utf8(buf) {
34+
Ok(s) => {
35+
assert_eq!(s.len(), 1);
36+
return s.chars().next();
37+
}
38+
Err(err) => {
39+
buf = err.as_bytes().to_vec();
40+
continue;
41+
}
42+
}
43+
}
44+
}
45+
}
46+
47+
impl Iterator for FileCharIterator {
48+
type Item = char;
49+
50+
fn next(&mut self) -> Option<Self::Item> {
51+
self.next_char()
52+
}
53+
}

0 commit comments

Comments
 (0)