]> git.ipfire.org Git - people/ms/suricata.git/blame - rust/src/applayer.rs
output/tx: implement filtering
[people/ms/suricata.git] / rust / src / applayer.rs
CommitLineData
2f5834cd 1/* Copyright (C) 2017-2020 Open Information Security Foundation
c54fc7f9
JI
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
2f5834cd
VJ
18//! Parser registration functions and common interface
19
e96d9c11 20use std;
e68dfa46 21use crate::core::{STREAM_TOSERVER};
2f5834cd
VJ
22use crate::core::{DetectEngineState,Flow,AppLayerEventType,AppLayerDecoderEvents,AppProto};
23use crate::filecontainer::FileContainer;
24use crate::applayer;
25use std::os::raw::{c_void,c_char,c_int};
26
411f428a
VJ
27#[repr(C)]
28#[derive(Debug,PartialEq)]
29pub struct AppLayerTxConfig {
30 /// config: log flags
31 log_flags: u8,
32}
33
34impl AppLayerTxConfig {
35 pub fn new() -> Self {
36 Self {
37 log_flags: 0,
38 }
39 }
40
41 pub fn add_log_flags(&mut self, flags: u8) {
42 self.log_flags |= flags;
43 }
44 pub fn set_log_flags(&mut self, flags: u8) {
45 self.log_flags = flags;
46 }
47 pub fn get_log_flags(&self) -> u8 {
48 self.log_flags
49 }
50}
51
52#[repr(C)]
53#[derive(Debug,PartialEq)]
54pub struct AppLayerTxData {
55 /// config: log flags
56 pub config: AppLayerTxConfig,
c797c9f0
VJ
57
58 /// logger flags for tx logging api
59 logged: LoggerFlags,
e15995e2
VJ
60
61 /// detection engine flags for use by detection engine
62 detect_flags_ts: u64,
63 detect_flags_tc: u64,
411f428a
VJ
64}
65
66impl AppLayerTxData {
67 pub fn new() -> Self {
68 Self {
69 config: AppLayerTxConfig::new(),
c797c9f0 70 logged: LoggerFlags::new(),
e15995e2
VJ
71 detect_flags_ts: 0,
72 detect_flags_tc: 0,
411f428a
VJ
73 }
74 }
75}
76
77#[macro_export]
78macro_rules!export_tx_data_get {
79 ($name:ident, $type:ty) => {
80 #[no_mangle]
81 pub unsafe extern "C" fn $name(tx: *mut std::os::raw::c_void)
82 -> *mut crate::applayer::AppLayerTxData
83 {
84 let tx = &mut *(tx as *mut $type);
85 &mut tx.tx_data
86 }
87 }
88}
89
2f5834cd 90#[repr(C)]
3a2434ed 91#[derive(Debug,PartialEq,Copy,Clone)]
2f5834cd
VJ
92pub struct AppLayerResult {
93 pub status: i32,
94 pub consumed: u32,
95 pub needed: u32,
96}
97
98impl AppLayerResult {
99 /// parser has successfully processed in the input, and has consumed all of it
100 pub fn ok() -> AppLayerResult {
101 return AppLayerResult {
102 status: 0,
103 consumed: 0,
104 needed: 0,
105 };
106 }
107 /// parser has hit an unrecoverable error. Returning this to the API
108 /// leads to no further calls to the parser.
109 pub fn err() -> AppLayerResult {
110 return AppLayerResult {
111 status: -1,
112 consumed: 0,
113 needed: 0,
114 };
115 }
116 /// parser needs more data. Through 'consumed' it will indicate how many
117 /// of the input bytes it has consumed. Through 'needed' it will indicate
118 /// how many more bytes it needs before getting called again.
119 /// Note: consumed should never be more than the input len
120 /// needed + consumed should be more than the input len
121 pub fn incomplete(consumed: u32, needed: u32) -> AppLayerResult {
122 return AppLayerResult {
123 status: 1,
124 consumed: consumed,
125 needed: needed,
126 };
127 }
b0288da6
VJ
128
129 pub fn is_ok(self) -> bool {
130 self.status == 0
131 }
132 pub fn is_incomplete(self) -> bool {
133 self.status == 1
134 }
135 pub fn is_err(self) -> bool {
136 self.status == -1
137 }
2f5834cd
VJ
138}
139
acef21b7
VJ
140impl From<bool> for AppLayerResult {
141 fn from(v: bool) -> Self {
142 if v == false {
143 Self::err()
144 } else {
145 Self::ok()
146 }
147 }
148}
149
150impl From<i32> for AppLayerResult {
151 fn from(v: i32) -> Self {
152 if v < 0 {
153 Self::err()
154 } else {
155 Self::ok()
156 }
157 }
158}
159
2f5834cd
VJ
160/// Rust parser declaration
161#[repr(C)]
162pub struct RustParser {
163 /// Parser name.
164 pub name: *const c_char,
165 /// Default port
166 pub default_port: *const c_char,
167
168 /// IP Protocol (core::IPPROTO_UDP, core::IPPROTO_TCP, etc.)
169 pub ipproto: c_int,
170
171 /// Probing function, for packets going to server
172 pub probe_ts: Option<ProbeFn>,
173 /// Probing function, for packets going to client
174 pub probe_tc: Option<ProbeFn>,
175
176 /// Minimum frame depth for probing
177 pub min_depth: u16,
178 /// Maximum frame depth for probing
179 pub max_depth: u16,
180
181 /// Allocation function for a new state
182 pub state_new: StateAllocFn,
183 /// Function called to free a state
184 pub state_free: StateFreeFn,
185
186 /// Parsing function, for packets going to server
187 pub parse_ts: ParseFn,
188 /// Parsing function, for packets going to client
189 pub parse_tc: ParseFn,
190
191 /// Get the current transaction count
192 pub get_tx_count: StateGetTxCntFn,
193 /// Get a transaction
194 pub get_tx: StateGetTxFn,
195 /// Function called to free a transaction
196 pub tx_free: StateTxFreeFn,
197 /// Function returning the current transaction completion status
198 pub tx_get_comp_st: StateGetTxCompletionStatusFn,
199 /// Function returning the current transaction progress
200 pub tx_get_progress: StateGetProgressFn,
201
202 /// Logged transaction getter function
203 pub get_tx_logged: Option<GetTxLoggedFn>,
204 /// Logged transaction setter function
205 pub set_tx_logged: Option<SetTxLoggedFn>,
206
207 /// Function called to get a detection state
208 pub get_de_state: GetDetectStateFn,
209 /// Function called to set a detection state
210 pub set_de_state: SetDetectStateFn,
211
212 /// Function to get events
213 pub get_events: Option<GetEventsFn>,
214 /// Function to get an event id from a description
215 pub get_eventinfo: Option<GetEventInfoFn>,
216 /// Function to get an event description from an event id
217 pub get_eventinfo_byid: Option<GetEventInfoByIdFn>,
218
219 /// Function to allocate local storage
220 pub localstorage_new: Option<LocalStorageNewFn>,
221 /// Function to free local storage
222 pub localstorage_free: Option<LocalStorageFreeFn>,
223
2f5834cd
VJ
224 /// Function to get files
225 pub get_files: Option<GetFilesFn>,
226
227 /// Function to get the TX iterator
228 pub get_tx_iterator: Option<GetTxIteratorFn>,
229
230 // Function to set TX detect flags.
231 pub set_tx_detect_flags: Option<SetTxDetectFlagsFn>,
232
233 // Function to get TX detect flags.
234 pub get_tx_detect_flags: Option<GetTxDetectFlagsFn>,
411f428a
VJ
235
236 pub get_tx_data: Option<GetTxDataFn>,
2f5834cd
VJ
237}
238
239/// Create a slice, given a buffer and a length
240///
241/// UNSAFE !
242#[macro_export]
243macro_rules! build_slice {
244 ($buf:ident, $len:expr) => ( unsafe{ std::slice::from_raw_parts($buf, $len) } );
245}
246
247/// Cast pointer to a variable, as a mutable reference to an object
248///
249/// UNSAFE !
250#[macro_export]
251macro_rules! cast_pointer {
252 ($ptr:ident, $ty:ty) => ( unsafe{ &mut *($ptr as *mut $ty) } );
253}
254
255pub type ParseFn = extern "C" fn (flow: *const Flow,
256 state: *mut c_void,
257 pstate: *mut c_void,
258 input: *const u8,
259 input_len: u32,
260 data: *const c_void,
261 flags: u8) -> AppLayerResult;
262pub type ProbeFn = extern "C" fn (flow: *const Flow,direction: u8,input:*const u8, input_len: u32, rdir: *mut u8) -> AppProto;
263pub type StateAllocFn = extern "C" fn () -> *mut c_void;
264pub type StateFreeFn = extern "C" fn (*mut c_void);
265pub type StateTxFreeFn = extern "C" fn (*mut c_void, u64);
266pub type StateGetTxFn = extern "C" fn (*mut c_void, u64) -> *mut c_void;
267pub type StateGetTxCntFn = extern "C" fn (*mut c_void) -> u64;
268pub type StateGetTxCompletionStatusFn = extern "C" fn (u8) -> c_int;
269pub type StateGetProgressFn = extern "C" fn (*mut c_void, u8) -> c_int;
270pub type GetDetectStateFn = extern "C" fn (*mut c_void) -> *mut DetectEngineState;
271pub type SetDetectStateFn = extern "C" fn (*mut c_void, &mut DetectEngineState) -> c_int;
272pub type GetEventInfoFn = extern "C" fn (*const c_char, *mut c_int, *mut AppLayerEventType) -> c_int;
273pub type GetEventInfoByIdFn = extern "C" fn (c_int, *mut *const c_char, *mut AppLayerEventType) -> i8;
274pub type GetEventsFn = extern "C" fn (*mut c_void) -> *mut AppLayerDecoderEvents;
275pub type GetTxLoggedFn = extern "C" fn (*mut c_void, *mut c_void) -> u32;
276pub type SetTxLoggedFn = extern "C" fn (*mut c_void, *mut c_void, u32);
277pub type LocalStorageNewFn = extern "C" fn () -> *mut c_void;
278pub type LocalStorageFreeFn = extern "C" fn (*mut c_void);
2f5834cd
VJ
279pub type GetFilesFn = extern "C" fn (*mut c_void, u8) -> *mut FileContainer;
280pub type GetTxIteratorFn = extern "C" fn (ipproto: u8, alproto: AppProto,
281 state: *mut c_void,
282 min_tx_id: u64,
283 max_tx_id: u64,
284 istate: &mut u64)
285 -> AppLayerGetTxIterTuple;
286pub type GetTxDetectFlagsFn = unsafe extern "C" fn(*mut c_void, u8) -> u64;
287pub type SetTxDetectFlagsFn = unsafe extern "C" fn(*mut c_void, u8, u64);
411f428a 288pub type GetTxDataFn = unsafe extern "C" fn(*mut c_void) -> *mut AppLayerTxData;
2f5834cd
VJ
289
290// Defined in app-layer-register.h
291extern {
292 pub fn AppLayerRegisterProtocolDetection(parser: *const RustParser, enable_default: c_int) -> AppProto;
293 pub fn AppLayerRegisterParser(parser: *const RustParser, alproto: AppProto) -> c_int;
294}
295
296// Defined in app-layer-detect-proto.h
297extern {
298 pub fn AppLayerProtoDetectConfProtoDetectionEnabled(ipproto: *const c_char, proto: *const c_char) -> c_int;
299}
300
301// Defined in app-layer-parser.h
302pub const APP_LAYER_PARSER_EOF : u8 = 0b0;
303pub const APP_LAYER_PARSER_NO_INSPECTION : u8 = 0b1;
304pub const APP_LAYER_PARSER_NO_REASSEMBLY : u8 = 0b10;
305pub const APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD : u8 = 0b100;
306pub const APP_LAYER_PARSER_BYPASS_READY : u8 = 0b1000;
e96d9c11 307
a0e3e2d7
JI
308pub const APP_LAYER_PARSER_OPT_ACCEPT_GAPS: u32 = BIT_U32!(0);
309
2f5834cd
VJ
310pub type AppLayerGetTxIteratorFn = extern "C" fn (ipproto: u8,
311 alproto: AppProto,
312 alstate: *mut c_void,
313 min_tx_id: u64,
314 max_tx_id: u64,
315 istate: &mut u64) -> applayer::AppLayerGetTxIterTuple;
316
317extern {
318 pub fn AppLayerParserStateSetFlag(state: *mut c_void, flag: u8);
319 pub fn AppLayerParserStateIssetFlag(state: *mut c_void, flag: u8) -> c_int;
320 pub fn AppLayerParserConfParserEnabled(ipproto: *const c_char, proto: *const c_char) -> c_int;
321 pub fn AppLayerParserRegisterGetTxIterator(ipproto: u8, alproto: AppProto, fun: AppLayerGetTxIteratorFn);
322 pub fn AppLayerParserRegisterDetectFlagsFuncs(
323 ipproto: u8,
324 alproto: AppProto,
325 GetTxDetectFlats: GetTxDetectFlagsFn,
326 SetTxDetectFlags: SetTxDetectFlagsFn,
327 );
328 pub fn AppLayerParserRegisterOptionFlags(ipproto: u8, alproto: AppProto, flags: u32);
329}
330
e96d9c11
VJ
331#[repr(C)]
332pub struct AppLayerGetTxIterTuple {
3f6624bf 333 tx_ptr: *mut std::os::raw::c_void,
e96d9c11
VJ
334 tx_id: u64,
335 has_next: bool,
336}
337
338impl AppLayerGetTxIterTuple {
3f6624bf 339 pub fn with_values(tx_ptr: *mut std::os::raw::c_void, tx_id: u64, has_next: bool) -> AppLayerGetTxIterTuple {
e96d9c11
VJ
340 AppLayerGetTxIterTuple {
341 tx_ptr: tx_ptr, tx_id: tx_id, has_next: has_next,
342 }
343 }
344 pub fn not_found() -> AppLayerGetTxIterTuple {
345 AppLayerGetTxIterTuple {
346 tx_ptr: std::ptr::null_mut(), tx_id: 0, has_next: false,
347 }
348 }
349}
350
c54fc7f9 351/// LoggerFlags tracks which loggers have already been executed.
c797c9f0
VJ
352#[repr(C)]
353#[derive(Debug,PartialEq)]
c54fc7f9
JI
354pub struct LoggerFlags {
355 flags: u32,
356}
357
358impl LoggerFlags {
359
360 pub fn new() -> LoggerFlags {
361 return LoggerFlags{
362 flags: 0,
363 }
364 }
365
bca0cd71
VJ
366 pub fn get(&self) -> u32 {
367 self.flags
368 }
369
370 pub fn set(&mut self, bits: u32) {
371 self.flags = bits;
372 }
373
c54fc7f9 374}
2ec33816
JI
375
376/// Export a function to get the DetectEngineState on a struct.
377#[macro_export]
378macro_rules!export_tx_get_detect_state {
379 ($name:ident, $type:ty) => (
380 #[no_mangle]
3f6624bf 381 pub extern "C" fn $name(tx: *mut std::os::raw::c_void)
2ec33816
JI
382 -> *mut core::DetectEngineState
383 {
384 let tx = cast_pointer!(tx, $type);
385 match tx.de_state {
386 Some(ds) => {
387 return ds;
388 },
389 None => {
390 return std::ptr::null_mut();
391 }
392 }
393 }
394 )
395}
396
397/// Export a function to set the DetectEngineState on a struct.
398#[macro_export]
399macro_rules!export_tx_set_detect_state {
400 ($name:ident, $type:ty) => (
401 #[no_mangle]
3f6624bf
VJ
402 pub extern "C" fn $name(tx: *mut std::os::raw::c_void,
403 de_state: &mut core::DetectEngineState) -> std::os::raw::c_int
2ec33816
JI
404 {
405 let tx = cast_pointer!(tx, $type);
406 tx.de_state = Some(de_state);
407 0
408 }
409 )
410}
8a232be7
JI
411
412#[derive(Debug,Default)]
413pub struct TxDetectFlags {
414 ts: u64,
415 tc: u64,
416}
417
418impl TxDetectFlags {
419 pub fn set(&mut self, direction: u8, flags: u64) {
420 if direction & STREAM_TOSERVER != 0 {
421 self.ts = flags;
422 } else {
423 self.tc = flags;
424 }
425 }
426
427 pub fn get(&self, direction: u8) -> u64 {
428 if (direction & STREAM_TOSERVER) != 0 {
429 self.ts
430 } else {
431 self.tc
432 }
433 }
434}
435
436#[macro_export]
437macro_rules!export_tx_detect_flags_set {
438 ($name:ident, $type:ty) => {
439 #[no_mangle]
440 pub unsafe extern "C" fn $name(tx: *mut std::os::raw::c_void, direction: u8, flags: u64) {
441 let tx = &mut *(tx as *mut $type);
442 tx.detect_flags.set(direction, flags);
443 }
444 }
445}
446
447#[macro_export]
448macro_rules!export_tx_detect_flags_get {
449 ($name:ident, $type:ty) => {
450 #[no_mangle]
451 pub unsafe extern "C" fn $name(tx: *mut std::os::raw::c_void, direction: u8) -> u64 {
452 let tx = &mut *(tx as *mut $type);
453 return tx.detect_flags.get(direction);
454 }
455 }
456}