]>
Commit | Line | Data |
---|---|---|
c78f5ac3 | 1 | /* Copyright (C) 2017-2021 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 | 20 | use std; |
7732efbe | 21 | use crate::core::{self,DetectEngineState,Flow,AppLayerEventType,AppProto}; |
2f5834cd VJ |
22 | use crate::filecontainer::FileContainer; |
23 | use crate::applayer; | |
24 | use std::os::raw::{c_void,c_char,c_int}; | |
3ada5e14 | 25 | use crate::core::SC; |
0fa7b5c2 | 26 | use std::ffi::CStr; |
2f5834cd | 27 | |
411f428a | 28 | #[repr(C)] |
f502f21f | 29 | #[derive(Default, Debug,PartialEq)] |
411f428a VJ |
30 | pub struct AppLayerTxConfig { |
31 | /// config: log flags | |
32 | log_flags: u8, | |
33 | } | |
34 | ||
35 | impl AppLayerTxConfig { | |
36 | pub fn new() -> Self { | |
37 | Self { | |
38 | log_flags: 0, | |
39 | } | |
40 | } | |
41 | ||
42 | pub fn add_log_flags(&mut self, flags: u8) { | |
43 | self.log_flags |= flags; | |
44 | } | |
45 | pub fn set_log_flags(&mut self, flags: u8) { | |
46 | self.log_flags = flags; | |
47 | } | |
48 | pub fn get_log_flags(&self) -> u8 { | |
49 | self.log_flags | |
50 | } | |
51 | } | |
52 | ||
53 | #[repr(C)] | |
9c67c634 | 54 | #[derive(Debug, PartialEq)] |
411f428a VJ |
55 | pub struct AppLayerTxData { |
56 | /// config: log flags | |
57 | pub config: AppLayerTxConfig, | |
c797c9f0 VJ |
58 | |
59 | /// logger flags for tx logging api | |
60 | logged: LoggerFlags, | |
e15995e2 | 61 | |
c78f5ac3 VJ |
62 | /// track file open/logs so we can know how long to keep the tx |
63 | pub files_opened: u32, | |
64 | pub files_logged: u32, | |
56d3e28a | 65 | pub files_stored: u32, |
c78f5ac3 | 66 | |
e15995e2 VJ |
67 | /// detection engine flags for use by detection engine |
68 | detect_flags_ts: u64, | |
69 | detect_flags_tc: u64, | |
9c67c634 JI |
70 | |
71 | de_state: *mut DetectEngineState, | |
7732efbe | 72 | pub events: *mut core::AppLayerDecoderEvents, |
9c67c634 JI |
73 | } |
74 | ||
75 | impl Default for AppLayerTxData { | |
76 | fn default() -> Self { | |
77 | Self::new() | |
78 | } | |
79 | } | |
80 | ||
81 | impl Drop for AppLayerTxData { | |
82 | fn drop(&mut self) { | |
83 | if self.de_state != std::ptr::null_mut() { | |
84 | core::sc_detect_engine_state_free(self.de_state); | |
85 | } | |
7732efbe JI |
86 | if self.events != std::ptr::null_mut() { |
87 | core::sc_app_layer_decoder_events_free_events(&mut self.events); | |
88 | } | |
9c67c634 | 89 | } |
411f428a VJ |
90 | } |
91 | ||
92 | impl AppLayerTxData { | |
93 | pub fn new() -> Self { | |
94 | Self { | |
95 | config: AppLayerTxConfig::new(), | |
c797c9f0 | 96 | logged: LoggerFlags::new(), |
c78f5ac3 VJ |
97 | files_opened: 0, |
98 | files_logged: 0, | |
56d3e28a | 99 | files_stored: 0, |
e15995e2 VJ |
100 | detect_flags_ts: 0, |
101 | detect_flags_tc: 0, | |
9c67c634 | 102 | de_state: std::ptr::null_mut(), |
7732efbe | 103 | events: std::ptr::null_mut(), |
411f428a VJ |
104 | } |
105 | } | |
c78f5ac3 VJ |
106 | pub fn init_files_opened(&mut self) { |
107 | self.files_opened = 1; | |
108 | } | |
109 | pub fn incr_files_opened(&mut self) { | |
110 | self.files_opened += 1; | |
111 | } | |
7732efbe JI |
112 | |
113 | pub fn set_event(&mut self, event: u8) { | |
114 | core::sc_app_layer_decoder_events_set_event_raw(&mut self.events, event as u8); | |
115 | } | |
411f428a VJ |
116 | } |
117 | ||
118 | #[macro_export] | |
119 | macro_rules!export_tx_data_get { | |
120 | ($name:ident, $type:ty) => { | |
121 | #[no_mangle] | |
122 | pub unsafe extern "C" fn $name(tx: *mut std::os::raw::c_void) | |
123 | -> *mut crate::applayer::AppLayerTxData | |
124 | { | |
125 | let tx = &mut *(tx as *mut $type); | |
126 | &mut tx.tx_data | |
127 | } | |
128 | } | |
129 | } | |
130 | ||
2f5834cd | 131 | #[repr(C)] |
aa8871a5 | 132 | #[derive(Default,Debug,PartialEq,Copy,Clone)] |
2f5834cd VJ |
133 | pub struct AppLayerResult { |
134 | pub status: i32, | |
135 | pub consumed: u32, | |
136 | pub needed: u32, | |
137 | } | |
138 | ||
139 | impl AppLayerResult { | |
140 | /// parser has successfully processed in the input, and has consumed all of it | |
aa8871a5 JL |
141 | pub fn ok() -> Self { |
142 | Default::default() | |
2f5834cd VJ |
143 | } |
144 | /// parser has hit an unrecoverable error. Returning this to the API | |
145 | /// leads to no further calls to the parser. | |
aa8871a5 JL |
146 | pub fn err() -> Self { |
147 | return Self { | |
2f5834cd | 148 | status: -1, |
aa8871a5 | 149 | ..Default::default() |
2f5834cd VJ |
150 | }; |
151 | } | |
152 | /// parser needs more data. Through 'consumed' it will indicate how many | |
153 | /// of the input bytes it has consumed. Through 'needed' it will indicate | |
154 | /// how many more bytes it needs before getting called again. | |
155 | /// Note: consumed should never be more than the input len | |
156 | /// needed + consumed should be more than the input len | |
aa8871a5 JL |
157 | pub fn incomplete(consumed: u32, needed: u32) -> Self { |
158 | return Self { | |
2f5834cd VJ |
159 | status: 1, |
160 | consumed: consumed, | |
161 | needed: needed, | |
162 | }; | |
163 | } | |
b0288da6 VJ |
164 | |
165 | pub fn is_ok(self) -> bool { | |
166 | self.status == 0 | |
167 | } | |
168 | pub fn is_incomplete(self) -> bool { | |
169 | self.status == 1 | |
170 | } | |
171 | pub fn is_err(self) -> bool { | |
172 | self.status == -1 | |
173 | } | |
2f5834cd VJ |
174 | } |
175 | ||
acef21b7 VJ |
176 | impl From<bool> for AppLayerResult { |
177 | fn from(v: bool) -> Self { | |
178 | if v == false { | |
179 | Self::err() | |
180 | } else { | |
181 | Self::ok() | |
182 | } | |
183 | } | |
184 | } | |
185 | ||
186 | impl From<i32> for AppLayerResult { | |
187 | fn from(v: i32) -> Self { | |
188 | if v < 0 { | |
189 | Self::err() | |
190 | } else { | |
191 | Self::ok() | |
192 | } | |
193 | } | |
194 | } | |
195 | ||
2f5834cd VJ |
196 | /// Rust parser declaration |
197 | #[repr(C)] | |
198 | pub struct RustParser { | |
199 | /// Parser name. | |
200 | pub name: *const c_char, | |
201 | /// Default port | |
202 | pub default_port: *const c_char, | |
203 | ||
204 | /// IP Protocol (core::IPPROTO_UDP, core::IPPROTO_TCP, etc.) | |
205 | pub ipproto: c_int, | |
206 | ||
207 | /// Probing function, for packets going to server | |
208 | pub probe_ts: Option<ProbeFn>, | |
209 | /// Probing function, for packets going to client | |
210 | pub probe_tc: Option<ProbeFn>, | |
211 | ||
212 | /// Minimum frame depth for probing | |
213 | pub min_depth: u16, | |
214 | /// Maximum frame depth for probing | |
215 | pub max_depth: u16, | |
216 | ||
217 | /// Allocation function for a new state | |
218 | pub state_new: StateAllocFn, | |
219 | /// Function called to free a state | |
220 | pub state_free: StateFreeFn, | |
221 | ||
222 | /// Parsing function, for packets going to server | |
223 | pub parse_ts: ParseFn, | |
224 | /// Parsing function, for packets going to client | |
225 | pub parse_tc: ParseFn, | |
226 | ||
227 | /// Get the current transaction count | |
228 | pub get_tx_count: StateGetTxCntFn, | |
229 | /// Get a transaction | |
230 | pub get_tx: StateGetTxFn, | |
231 | /// Function called to free a transaction | |
232 | pub tx_free: StateTxFreeFn, | |
efc9a7a3 VJ |
233 | /// Progress values at which the tx is considered complete in a direction |
234 | pub tx_comp_st_ts: c_int, | |
235 | pub tx_comp_st_tc: c_int, | |
2f5834cd VJ |
236 | /// Function returning the current transaction progress |
237 | pub tx_get_progress: StateGetProgressFn, | |
238 | ||
2f5834cd VJ |
239 | /// Function to get an event id from a description |
240 | pub get_eventinfo: Option<GetEventInfoFn>, | |
241 | /// Function to get an event description from an event id | |
242 | pub get_eventinfo_byid: Option<GetEventInfoByIdFn>, | |
243 | ||
244 | /// Function to allocate local storage | |
245 | pub localstorage_new: Option<LocalStorageNewFn>, | |
246 | /// Function to free local storage | |
247 | pub localstorage_free: Option<LocalStorageFreeFn>, | |
248 | ||
2f5834cd VJ |
249 | /// Function to get files |
250 | pub get_files: Option<GetFilesFn>, | |
251 | ||
252 | /// Function to get the TX iterator | |
253 | pub get_tx_iterator: Option<GetTxIteratorFn>, | |
254 | ||
c94a5e63 | 255 | pub get_tx_data: GetTxDataFn, |
5665fc83 VJ |
256 | |
257 | // Function to apply config to a TX. Optional. Normal (bidirectional) | |
258 | // transactions don't need to set this. It is meant for cases where | |
259 | // the requests and responses are not sharing tx. It is then up to | |
260 | // the implementation to make sure the config is applied correctly. | |
261 | pub apply_tx_config: Option<ApplyTxConfigFn>, | |
53aa967e JI |
262 | |
263 | pub flags: u32, | |
4da0d9bd VJ |
264 | |
265 | /// Function to handle the end of data coming on one of the sides | |
266 | /// due to the stream reaching its 'depth' limit. | |
267 | pub truncate: Option<TruncateFn>, | |
2f5834cd VJ |
268 | } |
269 | ||
270 | /// Create a slice, given a buffer and a length | |
271 | /// | |
272 | /// UNSAFE ! | |
273 | #[macro_export] | |
274 | macro_rules! build_slice { | |
363b5f99 | 275 | ($buf:ident, $len:expr) => ( std::slice::from_raw_parts($buf, $len) ); |
2f5834cd VJ |
276 | } |
277 | ||
278 | /// Cast pointer to a variable, as a mutable reference to an object | |
279 | /// | |
280 | /// UNSAFE ! | |
281 | #[macro_export] | |
282 | macro_rules! cast_pointer { | |
363b5f99 | 283 | ($ptr:ident, $ty:ty) => ( &mut *($ptr as *mut $ty) ); |
2f5834cd VJ |
284 | } |
285 | ||
363b5f99 | 286 | pub type ParseFn = unsafe extern "C" fn (flow: *const Flow, |
2f5834cd VJ |
287 | state: *mut c_void, |
288 | pstate: *mut c_void, | |
289 | input: *const u8, | |
290 | input_len: u32, | |
291 | data: *const c_void, | |
292 | flags: u8) -> AppLayerResult; | |
363b5f99 | 293 | pub type ProbeFn = unsafe extern "C" fn (flow: *const Flow, flags: u8, input:*const u8, input_len: u32, rdir: *mut u8) -> AppProto; |
547d6c2d | 294 | pub type StateAllocFn = extern "C" fn (*mut c_void, AppProto) -> *mut c_void; |
363b5f99 JI |
295 | pub type StateFreeFn = unsafe extern "C" fn (*mut c_void); |
296 | pub type StateTxFreeFn = unsafe extern "C" fn (*mut c_void, u64); | |
297 | pub type StateGetTxFn = unsafe extern "C" fn (*mut c_void, u64) -> *mut c_void; | |
298 | pub type StateGetTxCntFn = unsafe extern "C" fn (*mut c_void) -> u64; | |
299 | pub type StateGetProgressFn = unsafe extern "C" fn (*mut c_void, u8) -> c_int; | |
363b5f99 JI |
300 | pub type GetEventInfoFn = unsafe extern "C" fn (*const c_char, *mut c_int, *mut AppLayerEventType) -> c_int; |
301 | pub type GetEventInfoByIdFn = unsafe extern "C" fn (c_int, *mut *const c_char, *mut AppLayerEventType) -> i8; | |
2f5834cd VJ |
302 | pub type LocalStorageNewFn = extern "C" fn () -> *mut c_void; |
303 | pub type LocalStorageFreeFn = extern "C" fn (*mut c_void); | |
363b5f99 JI |
304 | pub type GetFilesFn = unsafe |
305 | extern "C" fn (*mut c_void, u8) -> *mut FileContainer; | |
306 | pub type GetTxIteratorFn = unsafe extern "C" fn (ipproto: u8, alproto: AppProto, | |
2f5834cd VJ |
307 | state: *mut c_void, |
308 | min_tx_id: u64, | |
309 | max_tx_id: u64, | |
310 | istate: &mut u64) | |
311 | -> AppLayerGetTxIterTuple; | |
411f428a | 312 | pub type GetTxDataFn = unsafe extern "C" fn(*mut c_void) -> *mut AppLayerTxData; |
5665fc83 | 313 | pub type ApplyTxConfigFn = unsafe extern "C" fn (*mut c_void, *mut c_void, c_int, AppLayerTxConfig); |
4da0d9bd VJ |
314 | pub type TruncateFn = unsafe extern "C" fn (*mut c_void, u8); |
315 | ||
2f5834cd VJ |
316 | |
317 | // Defined in app-layer-register.h | |
318 | extern { | |
319 | pub fn AppLayerRegisterProtocolDetection(parser: *const RustParser, enable_default: c_int) -> AppProto; | |
ab6171c4 | 320 | pub fn AppLayerRegisterParserAlias(parser_name: *const c_char, alias_name: *const c_char); |
3ada5e14 JI |
321 | } |
322 | ||
323 | #[allow(non_snake_case)] | |
324 | pub unsafe fn AppLayerRegisterParser(parser: *const RustParser, alproto: AppProto) -> c_int { | |
325 | (SC.unwrap().AppLayerRegisterParser)(parser, alproto) | |
2f5834cd VJ |
326 | } |
327 | ||
328 | // Defined in app-layer-detect-proto.h | |
329 | extern { | |
cb8bd8c6 SB |
330 | pub fn AppLayerProtoDetectPPRegister(ipproto: u8, portstr: *const c_char, alproto: AppProto, |
331 | min_depth: u16, max_depth: u16, dir: u8, | |
332 | pparser1: ProbeFn, pparser2: ProbeFn); | |
333 | pub fn AppLayerProtoDetectPPParseConfPorts(ipproto_name: *const c_char, ipproto: u8, | |
334 | alproto_name: *const c_char, alproto: AppProto, | |
335 | min_depth: u16, max_depth: u16, | |
336 | pparser_ts: ProbeFn, pparser_tc: ProbeFn) -> i32; | |
337 | pub fn AppLayerProtoDetectPMRegisterPatternCSwPP(ipproto: u8, alproto: AppProto, | |
d66ad96f SB |
338 | pattern: *const c_char, depth: u16, |
339 | offset: u16, direction: u8, ppfn: ProbeFn, | |
340 | pp_min_depth: u16, pp_max_depth: u16) -> c_int; | |
2f5834cd | 341 | pub fn AppLayerProtoDetectConfProtoDetectionEnabled(ipproto: *const c_char, proto: *const c_char) -> c_int; |
ea4a509a | 342 | pub fn AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto: *const c_char, proto: *const c_char, default: bool) -> c_int; |
2f5834cd VJ |
343 | } |
344 | ||
345 | // Defined in app-layer-parser.h | |
fdab22d9 PA |
346 | pub const APP_LAYER_PARSER_EOF_TS : u8 = BIT_U8!(5); |
347 | pub const APP_LAYER_PARSER_EOF_TC : u8 = BIT_U8!(6); | |
348 | pub const APP_LAYER_PARSER_NO_INSPECTION : u8 = BIT_U8!(1); | |
349 | pub const APP_LAYER_PARSER_NO_REASSEMBLY : u8 = BIT_U8!(2); | |
350 | pub const APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD : u8 = BIT_U8!(3); | |
351 | pub const APP_LAYER_PARSER_BYPASS_READY : u8 = BIT_U8!(4); | |
e96d9c11 | 352 | |
a0e3e2d7 | 353 | pub const APP_LAYER_PARSER_OPT_ACCEPT_GAPS: u32 = BIT_U32!(0); |
ac3cf6ff | 354 | pub const APP_LAYER_PARSER_OPT_UNIDIR_TXS: u32 = BIT_U32!(1); |
a0e3e2d7 | 355 | |
363b5f99 | 356 | pub type AppLayerGetTxIteratorFn = unsafe extern "C" fn (ipproto: u8, |
2f5834cd VJ |
357 | alproto: AppProto, |
358 | alstate: *mut c_void, | |
359 | min_tx_id: u64, | |
360 | max_tx_id: u64, | |
361 | istate: &mut u64) -> applayer::AppLayerGetTxIterTuple; | |
362 | ||
363 | extern { | |
364 | pub fn AppLayerParserStateSetFlag(state: *mut c_void, flag: u8); | |
365 | pub fn AppLayerParserStateIssetFlag(state: *mut c_void, flag: u8) -> c_int; | |
cb8bd8c6 | 366 | pub fn AppLayerParserSetStreamDepth(ipproto: u8, alproto: AppProto, stream_depth: u32); |
2f5834cd VJ |
367 | pub fn AppLayerParserConfParserEnabled(ipproto: *const c_char, proto: *const c_char) -> c_int; |
368 | pub fn AppLayerParserRegisterGetTxIterator(ipproto: u8, alproto: AppProto, fun: AppLayerGetTxIteratorFn); | |
2f5834cd VJ |
369 | pub fn AppLayerParserRegisterOptionFlags(ipproto: u8, alproto: AppProto, flags: u32); |
370 | } | |
371 | ||
e96d9c11 VJ |
372 | #[repr(C)] |
373 | pub struct AppLayerGetTxIterTuple { | |
3f6624bf | 374 | tx_ptr: *mut std::os::raw::c_void, |
e96d9c11 VJ |
375 | tx_id: u64, |
376 | has_next: bool, | |
377 | } | |
378 | ||
379 | impl AppLayerGetTxIterTuple { | |
3f6624bf | 380 | pub fn with_values(tx_ptr: *mut std::os::raw::c_void, tx_id: u64, has_next: bool) -> AppLayerGetTxIterTuple { |
e96d9c11 VJ |
381 | AppLayerGetTxIterTuple { |
382 | tx_ptr: tx_ptr, tx_id: tx_id, has_next: has_next, | |
383 | } | |
384 | } | |
385 | pub fn not_found() -> AppLayerGetTxIterTuple { | |
386 | AppLayerGetTxIterTuple { | |
387 | tx_ptr: std::ptr::null_mut(), tx_id: 0, has_next: false, | |
388 | } | |
389 | } | |
390 | } | |
391 | ||
c54fc7f9 | 392 | /// LoggerFlags tracks which loggers have already been executed. |
c797c9f0 | 393 | #[repr(C)] |
f502f21f | 394 | #[derive(Default, Debug,PartialEq)] |
c54fc7f9 JI |
395 | pub struct LoggerFlags { |
396 | flags: u32, | |
397 | } | |
398 | ||
399 | impl LoggerFlags { | |
400 | ||
aa8871a5 JL |
401 | pub fn new() -> Self { |
402 | Default::default() | |
c54fc7f9 JI |
403 | } |
404 | ||
bca0cd71 VJ |
405 | pub fn get(&self) -> u32 { |
406 | self.flags | |
407 | } | |
408 | ||
409 | pub fn set(&mut self, bits: u32) { | |
410 | self.flags = bits; | |
411 | } | |
412 | ||
c54fc7f9 | 413 | } |
2ec33816 | 414 | |
dbea7d63 JI |
415 | /// AppLayerEvent trait that will be implemented on enums that |
416 | /// derive AppLayerEvent. | |
417 | pub trait AppLayerEvent { | |
418 | /// Return the enum variant of the given ID. | |
419 | fn from_id(id: i32) -> Option<Self> where Self: std::marker::Sized; | |
420 | ||
421 | /// Convert the enum variant to a C-style string (suffixed with \0). | |
422 | fn to_cstring(&self) -> &str; | |
423 | ||
0fa7b5c2 JI |
424 | /// Return the enum variant for the given name. |
425 | fn from_string(s: &str) -> Option<Self> where Self: std::marker::Sized; | |
dbea7d63 JI |
426 | |
427 | /// Return the ID value of the enum variant. | |
428 | fn as_i32(&self) -> i32; | |
9221f1d9 JI |
429 | |
430 | unsafe extern "C" fn get_event_info( | |
431 | event_name: *const std::os::raw::c_char, | |
432 | event_id: *mut std::os::raw::c_int, | |
433 | event_type: *mut core::AppLayerEventType, | |
434 | ) -> std::os::raw::c_int; | |
435 | ||
436 | unsafe extern "C" fn get_event_info_by_id( | |
437 | event_id: std::os::raw::c_int, | |
438 | event_name: *mut *const std::os::raw::c_char, | |
439 | event_type: *mut core::AppLayerEventType, | |
440 | ) -> i8; | |
dbea7d63 | 441 | } |
0fa7b5c2 JI |
442 | |
443 | /// Generic `get_info_info` implementation for enums implementing | |
444 | /// AppLayerEvent. | |
445 | /// | |
446 | /// Normally usage of this function will be generated by | |
447 | /// derive(AppLayerEvent), for example: | |
448 | /// | |
449 | /// #[derive(AppLayerEvent)] | |
450 | /// enum AppEvent { | |
451 | /// EventOne, | |
452 | /// EventTwo, | |
453 | /// } | |
454 | /// | |
455 | /// get_event_info::<AppEvent>(...) | |
456 | #[inline(always)] | |
9221f1d9 | 457 | pub unsafe fn get_event_info<T: AppLayerEvent>( |
0fa7b5c2 JI |
458 | event_name: *const std::os::raw::c_char, |
459 | event_id: *mut std::os::raw::c_int, | |
460 | event_type: *mut core::AppLayerEventType, | |
461 | ) -> std::os::raw::c_int { | |
23768c71 | 462 | if event_name.is_null() { |
0fa7b5c2 JI |
463 | return -1; |
464 | } | |
465 | ||
9221f1d9 JI |
466 | let event = match CStr::from_ptr(event_name).to_str().map(T::from_string) { |
467 | Ok(Some(event)) => event.as_i32(), | |
468 | _ => -1, | |
469 | }; | |
470 | *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; | |
471 | *event_id = event as std::os::raw::c_int; | |
472 | return 0; | |
0fa7b5c2 JI |
473 | } |
474 | ||
475 | /// Generic `get_info_info_by_id` implementation for enums implementing | |
476 | /// AppLayerEvent. | |
477 | #[inline(always)] | |
9221f1d9 | 478 | pub unsafe fn get_event_info_by_id<T: AppLayerEvent>( |
0fa7b5c2 JI |
479 | event_id: std::os::raw::c_int, |
480 | event_name: *mut *const std::os::raw::c_char, | |
481 | event_type: *mut core::AppLayerEventType, | |
482 | ) -> i8 { | |
483 | if let Some(e) = T::from_id(event_id as i32) { | |
9221f1d9 JI |
484 | *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char; |
485 | *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION; | |
0fa7b5c2 JI |
486 | return 0; |
487 | } | |
488 | return -1; | |
489 | } | |
049d4321 JI |
490 | |
491 | /// Transaction trait. | |
492 | /// | |
493 | /// This trait defines methods that a Transaction struct must implement | |
494 | /// in order to define some generic helper functions. | |
495 | pub trait Transaction { | |
496 | fn id(&self) -> u64; | |
497 | } | |
498 | ||
499 | pub trait State<Tx: Transaction> { | |
500 | fn get_transactions(&self) -> &[Tx]; | |
501 | ||
502 | fn get_transaction_iterator(&self, min_tx_id: u64, state: &mut u64) -> AppLayerGetTxIterTuple { | |
503 | let mut index = *state as usize; | |
504 | let transactions = self.get_transactions(); | |
505 | let len = transactions.len(); | |
506 | while index < len { | |
507 | let tx = &transactions[index]; | |
508 | if tx.id() < min_tx_id + 1 { | |
509 | index += 1; | |
510 | continue; | |
511 | } | |
512 | *state = index as u64; | |
513 | return AppLayerGetTxIterTuple::with_values( | |
514 | tx as *const _ as *mut _, | |
515 | tx.id() - 1, | |
516 | len - index > 1, | |
517 | ); | |
518 | } | |
519 | return AppLayerGetTxIterTuple::not_found(); | |
520 | } | |
521 | } | |
522 | ||
523 | pub unsafe extern "C" fn state_get_tx_iterator<S: State<Tx>, Tx: Transaction>( | |
524 | _ipproto: u8, _alproto: AppProto, state: *mut std::os::raw::c_void, min_tx_id: u64, | |
525 | _max_tx_id: u64, istate: &mut u64, | |
526 | ) -> AppLayerGetTxIterTuple { | |
527 | let state = cast_pointer!(state, S); | |
528 | state.get_transaction_iterator(min_tx_id, istate) | |
529 | } |