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 // This file exposes items from the core "C" code to Rust.
19 
20 use std;
21 use crate::filecontainer::*;
22 
23 /// Opaque C types.
24 pub enum DetectEngineState {}
25 pub enum AppLayerDecoderEvents {}
26 pub enum AppLayerParserState {}
27 
28 // From app-layer-events.h
29 pub type AppLayerEventType = std::os::raw::c_int;
30 pub const APP_LAYER_EVENT_TYPE_TRANSACTION : i32 = 1;
31 pub const APP_LAYER_EVENT_TYPE_PACKET      : i32 = 2;
32 
33 // From stream.h.
34 pub const STREAM_START:    u8 = 0x01;
35 pub const STREAM_EOF:      u8 = 0x02;
36 pub const STREAM_TOSERVER: u8 = 0x04;
37 pub const STREAM_TOCLIENT: u8 = 0x08;
38 pub const STREAM_GAP:      u8 = 0x10;
39 pub const STREAM_DEPTH:    u8 = 0x20;
40 pub const STREAM_MIDSTREAM:u8 = 0x40;
41 
42 // Application layer protocol identifiers (app-layer-protos.h)
43 pub type AppProto = std::os::raw::c_int;
44 
45 pub const ALPROTO_UNKNOWN : AppProto = 0;
46 pub static mut ALPROTO_FAILED : AppProto = 0; // updated during init
47 
48 pub const IPPROTO_TCP : i32 = 6;
49 pub const IPPROTO_UDP : i32 = 17;
50 
51 macro_rules!BIT_U8 {
52     ($x:expr) => (1 << $x);
53 }
54 
55 macro_rules!BIT_U16 {
56     ($x:expr) => (1 << $x);
57 }
58 
59 macro_rules!BIT_U32 {
60     ($x:expr) => (1 << $x);
61 }
62 
63 macro_rules!BIT_U64 {
64     ($x:expr) => (1 << $x);
65 }
66 
67 // Defined in app-layer-protos.h
68 extern {
StringToAppProto(proto_name: *const u8) -> AppProto69     pub fn StringToAppProto(proto_name: *const u8) -> AppProto;
70 }
71 
72 //
73 // Function types for calls into C.
74 //
75 
76 #[allow(non_snake_case)]
77 pub type SCLogMessageFunc =
78     extern "C" fn(level: std::os::raw::c_int,
79                   filename: *const std::os::raw::c_char,
80                   line: std::os::raw::c_uint,
81                   function: *const std::os::raw::c_char,
82                   code: std::os::raw::c_int,
83                   message: *const std::os::raw::c_char) -> std::os::raw::c_int;
84 
85 pub type DetectEngineStateFreeFunc =
86     extern "C" fn(state: *mut DetectEngineState);
87 
88 pub type AppLayerParserTriggerRawStreamReassemblyFunc =
89     extern "C" fn (flow: *const Flow, direction: i32);
90 pub type AppLayerDecoderEventsSetEventRawFunc =
91     extern "C" fn (events: *mut *mut AppLayerDecoderEvents,
92                    event: u8);
93 
94 pub type AppLayerDecoderEventsFreeEventsFunc =
95     extern "C" fn (events: *mut *mut AppLayerDecoderEvents);
96 
97 pub enum SuricataStreamingBufferConfig {}
98 
99 pub type SCFileOpenFileWithId = extern "C" fn (
100         file_container: &FileContainer,
101         sbcfg: &SuricataStreamingBufferConfig,
102         track_id: u32,
103         name: *const u8, name_len: u16,
104         data: *const u8, data_len: u32,
105         flags: u16) -> i32;
106 pub type SCFileCloseFileById = extern "C" fn (
107         file_container: &FileContainer,
108         track_id: u32,
109         data: *const u8, data_len: u32,
110         flags: u16) -> i32;
111 pub type SCFileAppendDataById = extern "C" fn (
112         file_container: &FileContainer,
113         track_id: u32,
114         data: *const u8, data_len: u32) -> i32;
115 pub type SCFileAppendGAPById = extern "C" fn (
116         file_container: &FileContainer,
117         track_id: u32,
118         data: *const u8, data_len: u32) -> i32;
119 pub type SCFilePrune = extern "C" fn (
120         file_container: &FileContainer);
121 pub type SCFileContainerRecycle = extern "C" fn (
122         file_container: &FileContainer);
123 
124 pub type SCFileSetTx = extern "C" fn (
125         file: &FileContainer,
126         tx_id: u64);
127 
128 // A Suricata context that is passed in from C. This is alternative to
129 // using functions from Suricata directly, so they can be wrapped so
130 // Rust unit tests will still compile when they are not linked
131 // directly to the real function.
132 //
133 // This might add a little too much complexity to keep pure Rust test
134 // cases working.
135 #[allow(non_snake_case)]
136 #[repr(C)]
137 pub struct SuricataContext {
138     pub SCLogMessage: SCLogMessageFunc,
139     DetectEngineStateFree: DetectEngineStateFreeFunc,
140     AppLayerDecoderEventsSetEventRaw: AppLayerDecoderEventsSetEventRawFunc,
141     AppLayerDecoderEventsFreeEvents: AppLayerDecoderEventsFreeEventsFunc,
142     pub AppLayerParserTriggerRawStreamReassembly: AppLayerParserTriggerRawStreamReassemblyFunc,
143 
144     pub FileOpenFile: SCFileOpenFileWithId,
145     pub FileCloseFile: SCFileCloseFileById,
146     pub FileAppendData: SCFileAppendDataById,
147     pub FileAppendGAP: SCFileAppendGAPById,
148     pub FileContainerRecycle: SCFileContainerRecycle,
149     pub FilePrune: SCFilePrune,
150     pub FileSetTx: SCFileSetTx,
151 }
152 
153 #[allow(non_snake_case)]
154 #[repr(C)]
155 pub struct SuricataFileContext {
156     pub files_sbcfg: &'static SuricataStreamingBufferConfig,
157 }
158 
159 extern {
SCGetContext() -> &'static mut SuricataContext160     pub fn SCGetContext() -> &'static mut SuricataContext;
SCLogGetLogLevel() -> i32161     pub fn SCLogGetLogLevel() -> i32;
162 }
163 
164 pub static mut SC: Option<&'static SuricataContext> = None;
165 
init_ffi(context: &'static mut SuricataContext)166 pub fn init_ffi(context: &'static mut SuricataContext)
167 {
168     unsafe {
169         SC = Some(context);
170         ALPROTO_FAILED = StringToAppProto("failed\0".as_ptr());
171     }
172 }
173 
174 #[no_mangle]
rs_init(context: &'static mut SuricataContext)175 pub extern "C" fn rs_init(context: &'static mut SuricataContext)
176 {
177     init_ffi(context);
178 }
179 
180 /// DetectEngineStateFree wrapper.
sc_detect_engine_state_free(state: *mut DetectEngineState)181 pub fn sc_detect_engine_state_free(state: *mut DetectEngineState)
182 {
183     unsafe {
184         if let Some(c) = SC {
185             (c.DetectEngineStateFree)(state);
186         }
187     }
188 }
189 
190 /// AppLayerParserTriggerRawStreamReassembly wrapper
sc_app_layer_parser_trigger_raw_stream_reassembly(flow: *const Flow, direction: i32)191 pub fn sc_app_layer_parser_trigger_raw_stream_reassembly(flow: *const Flow, direction: i32) {
192     unsafe {
193         if let Some(c) = SC {
194             (c.AppLayerParserTriggerRawStreamReassembly)(flow, direction);
195         }
196     }
197 }
198 
199 /// AppLayerDecoderEventsSetEventRaw wrapper.
sc_app_layer_decoder_events_set_event_raw( events: *mut *mut AppLayerDecoderEvents, event: u8)200 pub fn sc_app_layer_decoder_events_set_event_raw(
201     events: *mut *mut AppLayerDecoderEvents, event: u8)
202 {
203     unsafe {
204         if let Some(c) = SC {
205             (c.AppLayerDecoderEventsSetEventRaw)(events, event);
206         }
207     }
208 }
209 
210 /// AppLayerDecoderEventsFreeEvents wrapper.
sc_app_layer_decoder_events_free_events( events: *mut *mut AppLayerDecoderEvents)211 pub fn sc_app_layer_decoder_events_free_events(
212     events: *mut *mut AppLayerDecoderEvents)
213 {
214     unsafe {
215         if let Some(c) = SC {
216             (c.AppLayerDecoderEventsFreeEvents)(events);
217         }
218     }
219 }
220 
221 /// Opaque flow type (defined in C)
222 pub enum Flow {}
223 
224 /// Extern functions operating on Flow.
225 extern {
FlowGetLastTimeAsParts(flow: &Flow, secs: *mut u64, usecs: *mut u64)226     pub fn FlowGetLastTimeAsParts(flow: &Flow, secs: *mut u64, usecs: *mut u64);
227 }
228 
229 /// Rust implementation of Flow.
230 impl Flow {
231 
232     /// Return the time of the last flow update as a `Duration`
233     /// since the epoch.
get_last_time(&mut self) -> std::time::Duration234     pub fn get_last_time(&mut self) -> std::time::Duration {
235         unsafe {
236             let mut secs: u64 = 0;
237             let mut usecs: u64 = 0;
238             FlowGetLastTimeAsParts(self, &mut secs, &mut usecs);
239             std::time::Duration::new(secs, usecs as u32 * 1000)
240         }
241     }
242 }
243