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