From a809f090d3ae2f87d438a6a9ef59f54cd1d45f0d Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 11 May 2017 16:58:55 +0200 Subject: [PATCH] rust: filecontainer API Wrapper around Suricata's File and FileContainer API. Built around assumption that a rust owned structure will have a 'SuricataFileContainer' member that is managed by the C-side of things. --- rust/src/core.rs | 45 +++++++++++++++ rust/src/filecontainer.rs | 118 ++++++++++++++++++++++++++++++++++++++ rust/src/lib.rs | 3 + src/rust.h | 11 ++++ src/suricata.c | 7 +++ 5 files changed, 184 insertions(+) create mode 100644 rust/src/filecontainer.rs diff --git a/rust/src/core.rs b/rust/src/core.rs index 8388da2733..fb6edd26eb 100644 --- a/rust/src/core.rs +++ b/rust/src/core.rs @@ -19,6 +19,8 @@ extern crate libc; +use filecontainer::*; + /// Opaque C types. pub enum Flow {} pub enum DetectEngineState {} @@ -55,6 +57,37 @@ pub type AppLayerDecoderEventsSetEventRawFunc = pub type AppLayerDecoderEventsFreeEventsFunc = extern "C" fn (events: *mut *mut AppLayerDecoderEvents); +pub struct SuricataStreamingBufferConfig; + +//File *(*FileOpenFile)(FileContainer *, const StreamingBufferConfig *, +// const uint8_t *name, uint16_t name_len, +// const uint8_t *data, uint32_t data_len, uint16_t flags); +pub type SCFileOpenFileWithId = extern "C" fn ( + file_container: &FileContainer, + sbcfg: &SuricataStreamingBufferConfig, + track_id: u32, + name: *const u8, name_len: u16, + data: *const u8, data_len: u32, + flags: u16) -> File; +//int (*FileCloseFile)(FileContainer *, const uint8_t *data, uint32_t data_len, uint16_t flags); +pub type SCFileCloseFileById = extern "C" fn ( + file_container: &FileContainer, + track_id: u32, + data: *const u8, data_len: u32, + flags: u16) -> i32; +//int (*FileAppendData)(FileContainer *, const uint8_t *data, uint32_t data_len); +pub type SCFileAppendDataById = extern "C" fn ( + file_container: &FileContainer, + track_id: u32, + data: *const u8, data_len: u32) -> i32; +// void FilePrune(FileContainer *ffc) +pub type SCFilePrune = extern "C" fn ( + file_container: &FileContainer); +// void FileContainerRecycle(FileContainer *ffc) +pub type SCFileContainerRecycle = extern "C" fn ( + file_container: &FileContainer); + + // A Suricata context that is passed in from C. This is alternative to // using functions from Suricata directly, so they can be wrapped so // Rust unit tests will still compile when they are not linked @@ -69,6 +102,18 @@ pub struct SuricataContext { DetectEngineStateFree: DetectEngineStateFreeFunc, AppLayerDecoderEventsSetEventRaw: AppLayerDecoderEventsSetEventRawFunc, AppLayerDecoderEventsFreeEvents: AppLayerDecoderEventsFreeEventsFunc, + + pub FileOpenFile: SCFileOpenFileWithId, + pub FileCloseFile: SCFileCloseFileById, + pub FileAppendData: SCFileAppendDataById, + pub FileContainerRecycle: SCFileContainerRecycle, + pub FilePrune: SCFilePrune, +} + +#[allow(non_snake_case)] +#[repr(C)] +pub struct SuricataFileContext { + pub files_sbcfg: &'static SuricataStreamingBufferConfig, } pub static mut SC: Option<&'static SuricataContext> = None; diff --git a/rust/src/filecontainer.rs b/rust/src/filecontainer.rs new file mode 100644 index 0000000000..3d3c163d94 --- /dev/null +++ b/rust/src/filecontainer.rs @@ -0,0 +1,118 @@ +/* Copyright (C) 2017 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 + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +extern crate libc; +use std::ptr; +use libc::{c_void}; + +use log::*; +use core::*; + +pub struct File; +#[repr(C)] +#[derive(Debug)] +pub struct FileContainer { + head: * mut c_void, + tail: * mut c_void, +} + +impl FileContainer { + pub fn default() -> FileContainer { + FileContainer { head:ptr::null_mut(), tail:ptr::null_mut() } + } + pub fn free(&mut self) { + SCLogDebug!("freeing self"); + match unsafe {SC} { + None => panic!("BUG no suricata_config"), + Some(c) => { + (c.FileContainerRecycle)(&self); + }, + } + } + + pub fn file_open(&mut self, cfg: &'static SuricataFileContext, track_id: &u32, name: &[u8], flags: u16) -> i32 { + match unsafe {SC} { + None => panic!("BUG no suricata_config"), + Some(c) => { + SCLogDebug!("FILE {:p} OPEN flags {:04X}", &self, flags); + //let ref res = + + (c.FileOpenFile)(&self, cfg.files_sbcfg, *track_id, + name.as_ptr(), name.len() as u16, + ptr::null(), 0u32, flags); + + //if !res { + // panic!("c.fn_fileopenfile failed"); + //} + 0 + } + } + } + + pub fn file_append(&mut self, track_id: &u32, data: &[u8]) -> i32 { + SCLogDebug!("FILECONTAINER: append {}", data.len()); + if data.len() == 0 { + return 0 + } + match unsafe {SC} { + None => panic!("BUG no suricata_config"), + Some(c) => { + let res = (c.FileAppendData)(&self, *track_id, + data.as_ptr(), data.len() as u32); + if res != 0 { + panic!("c.fn_fileappenddata failed"); + } + res + } + } + } + + pub fn file_close(&mut self, track_id: &u32, flags: u16) -> i32 { + SCLogDebug!("FILECONTAINER: CLOSEing"); + + match unsafe {SC} { + None => panic!("BUG no suricata_config"), + Some(c) => { + let res = (c.FileCloseFile)(&self, *track_id, ptr::null(), 0u32, flags); + if res != 0 { + panic!("c.fn_fileclosefile failed"); + } + res + } + } + + } + + pub fn files_prune(&mut self) { + SCLogDebug!("FILECONTAINER: pruning"); + match unsafe {SC} { + None => panic!("BUG no suricata_config"), + Some(c) => { + (c.FilePrune)(&self); + } + } + } + + pub fn file_set_txid_on_last_file(&mut self, tx_id: u64) { + match unsafe {SC} { + None => panic!("BUG no suricata_config"), + Some(c) => { + (c.FileSetTx)(&self, tx_id); + } + } + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index aa214304d6..a80c14b417 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -15,6 +15,8 @@ * 02110-1301, USA. */ +extern crate libc; + #[macro_use] extern crate nom; @@ -27,6 +29,7 @@ pub mod core; pub mod conf; pub mod json; pub mod applayer; +pub mod filecontainer; #[cfg(feature = "lua")] pub mod lua; diff --git a/src/rust.h b/src/rust.h index b5ee1b5038..0dcf54f7a0 100644 --- a/src/rust.h +++ b/src/rust.h @@ -25,6 +25,17 @@ typedef struct SuricataContext_ { void (*AppLayerDecoderEventsSetEventRaw)(AppLayerDecoderEvents **, uint8_t); void (*AppLayerDecoderEventsFreeEvents)(AppLayerDecoderEvents **); + + File *(*FileOpenFileWithId)(FileContainer *, const StreamingBufferConfig *, + uint32_t track_id, const uint8_t *name, uint16_t name_len, + const uint8_t *data, uint32_t data_len, uint16_t flags); + int (*FileCloseFileById)(FileContainer *, uint32_t track_id, + const uint8_t *data, uint32_t data_len, uint16_t flags); + int (*FileAppendDataById)(FileContainer *, uint32_t track_id, + const uint8_t *data, uint32_t data_len); + void (*FileContainerRecycle)(FileContainer *ffc); + void (*FilePrune)(FileContainer *ffc); + } SuricataContext; #endif /* !__RUST_H__ */ diff --git a/src/suricata.c b/src/suricata.c index afda25d67e..a5f76a40f8 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -2786,6 +2786,13 @@ int main(int argc, char **argv) context.AppLayerDecoderEventsSetEventRaw = AppLayerDecoderEventsSetEventRaw; context.AppLayerDecoderEventsFreeEvents = AppLayerDecoderEventsFreeEvents; + + context.FileOpenFileWithId = FileOpenFileWithId; + context.FileCloseFileById = FileCloseFileById; + context.FileAppendDataById = FileAppendDataById; + context.FileContainerRecycle = FileContainerRecycle; + context.FilePrune = FilePrune; + rs_init(&context); #endif