]>
Commit | Line | Data |
---|---|---|
e2dbdd7f | 1 | /* Copyright (C) 2020 Open Information Security Foundation |
c99b9462 PC |
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 | ||
e2dbdd7f | 18 | // Author: Frank Honza <frank.honza@dcso.de> |
c99b9462 | 19 | |
e2dbdd7f SS |
20 | extern crate ipsec_parser; |
21 | use self::ipsec_parser::*; | |
c99b9462 | 22 | |
e2dbdd7f SS |
23 | use crate::applayer; |
24 | use crate::applayer::*; | |
25 | use crate::core::{ | |
26 | self, AppProto, Flow, ALPROTO_FAILED, ALPROTO_UNKNOWN, STREAM_TOCLIENT, STREAM_TOSERVER, | |
27 | }; | |
28 | use crate::ike::ikev1::{handle_ikev1, IkeV1Header, Ikev1Container}; | |
29 | use crate::ike::ikev2::{handle_ikev2, Ikev2Container}; | |
30 | use crate::ike::parser::*; | |
13b73997 | 31 | use nom; |
e2dbdd7f SS |
32 | use std; |
33 | use std::collections::HashSet; | |
71679c6a | 34 | use std::ffi::CString; |
c99b9462 | 35 | |
71679c6a | 36 | #[derive(AppLayerEvent)] |
ecdf9f6b | 37 | pub enum IkeEvent { |
71679c6a | 38 | MalformedData, |
c99b9462 PC |
39 | NoEncryption, |
40 | WeakCryptoEnc, | |
71679c6a JI |
41 | WeakCryptoPrf, |
42 | WeakCryptoDh, | |
c99b9462 | 43 | WeakCryptoAuth, |
71679c6a | 44 | WeakCryptoNoDh, |
c99b9462 PC |
45 | WeakCryptoNoAuth, |
46 | InvalidProposal, | |
47 | UnknownProposal, | |
e2dbdd7f | 48 | PayloadExtraData, |
f83d51d0 | 49 | MultipleServerProposal, |
c99b9462 PC |
50 | } |
51 | ||
e2dbdd7f SS |
52 | pub struct IkeHeaderWrapper { |
53 | pub spi_initiator: String, | |
54 | pub spi_responder: String, | |
55 | pub maj_ver: u8, | |
56 | pub min_ver: u8, | |
57 | pub msg_id: u32, | |
58 | pub flags: u8, | |
59 | pub ikev1_transforms: Vec<Vec<SaAttribute>>, | |
accdad78 | 60 | pub ikev2_transforms: Vec<IkeV2Transform>, |
e2dbdd7f SS |
61 | pub ikev1_header: IkeV1Header, |
62 | pub ikev2_header: IkeV2Header, | |
63 | } | |
c99b9462 | 64 | |
e2dbdd7f SS |
65 | impl IkeHeaderWrapper { |
66 | pub fn new() -> IkeHeaderWrapper { | |
67 | IkeHeaderWrapper { | |
68 | spi_initiator: String::new(), | |
69 | spi_responder: String::new(), | |
70 | maj_ver: 0, | |
71 | min_ver: 0, | |
72 | msg_id: 0, | |
73 | flags: 0, | |
74 | ikev1_transforms: Vec::new(), | |
75 | ikev2_transforms: Vec::new(), | |
76 | ikev1_header: IkeV1Header::default(), | |
77 | ikev2_header: IkeV2Header { | |
78 | init_spi: 0, | |
79 | resp_spi: 0, | |
80 | next_payload: IkePayloadType::NoNextPayload, | |
81 | maj_ver: 0, | |
82 | min_ver: 0, | |
83 | exch_type: IkeExchangeType(0), | |
84 | flags: 0, | |
85 | msg_id: 0, | |
86 | length: 0, | |
87 | }, | |
88 | } | |
89 | } | |
90 | } | |
c99b9462 | 91 | |
e2dbdd7f SS |
92 | #[derive(Default)] |
93 | pub struct IkePayloadWrapper { | |
94 | pub ikev1_payload_types: Option<HashSet<u8>>, | |
95 | pub ikev2_payload_types: Vec<IkePayloadType>, | |
c99b9462 PC |
96 | } |
97 | ||
ecdf9f6b | 98 | pub struct IKETransaction { |
e2dbdd7f | 99 | tx_id: u64, |
c99b9462 | 100 | |
e2dbdd7f SS |
101 | pub ike_version: u8, |
102 | pub hdr: IkeHeaderWrapper, | |
103 | pub payload_types: IkePayloadWrapper, | |
d9434628 PC |
104 | pub notify_types: Vec<NotifyType>, |
105 | ||
e2dbdd7f | 106 | /// errors seen during exchange |
d9434628 PC |
107 | pub errors: u32, |
108 | ||
e2dbdd7f | 109 | logged: LoggerFlags, |
c99b9462 | 110 | de_state: Option<*mut core::DetectEngineState>, |
c99b9462 | 111 | events: *mut core::AppLayerDecoderEvents, |
e0f75157 | 112 | tx_data: applayer::AppLayerTxData, |
c99b9462 PC |
113 | } |
114 | ||
e2dbdd7f SS |
115 | impl IKETransaction { |
116 | pub fn new() -> IKETransaction { | |
117 | IKETransaction { | |
c99b9462 | 118 | tx_id: 0, |
e2dbdd7f SS |
119 | ike_version: 0, |
120 | hdr: IkeHeaderWrapper::new(), | |
121 | payload_types: Default::default(), | |
122 | notify_types: vec![], | |
123 | logged: LoggerFlags::new(), | |
124 | de_state: None, | |
125 | events: std::ptr::null_mut(), | |
126 | tx_data: applayer::AppLayerTxData::new(), | |
127 | errors: 0, | |
c99b9462 PC |
128 | } |
129 | } | |
c99b9462 | 130 | |
e2dbdd7f | 131 | pub fn free(&mut self) { |
922a453d | 132 | if !self.events.is_null() { |
e2dbdd7f SS |
133 | core::sc_app_layer_decoder_events_free_events(&mut self.events); |
134 | } | |
135 | if let Some(state) = self.de_state { | |
136 | core::sc_detect_engine_state_free(state); | |
c99b9462 PC |
137 | } |
138 | } | |
accdad78 PA |
139 | |
140 | /// Set an event. | |
141 | pub fn set_event(&mut self, event: IkeEvent) { | |
142 | let ev = event as u8; | |
143 | core::sc_app_layer_decoder_events_set_event_raw(&mut self.events, ev); | |
144 | } | |
e2dbdd7f | 145 | } |
c99b9462 | 146 | |
e2dbdd7f SS |
147 | impl Drop for IKETransaction { |
148 | fn drop(&mut self) { | |
149 | self.free(); | |
c99b9462 | 150 | } |
e2dbdd7f | 151 | } |
c99b9462 | 152 | |
e2dbdd7f SS |
153 | #[derive(Default)] |
154 | pub struct IKEState { | |
155 | tx_id: u64, | |
156 | pub transactions: Vec<IKETransaction>, | |
c99b9462 | 157 | |
e2dbdd7f SS |
158 | pub ikev1_container: Ikev1Container, |
159 | pub ikev2_container: Ikev2Container, | |
160 | } | |
c99b9462 | 161 | |
e2dbdd7f SS |
162 | impl IKEState { |
163 | // Free a transaction by ID. | |
c99b9462 | 164 | fn free_tx(&mut self, tx_id: u64) { |
e2dbdd7f SS |
165 | let tx = self |
166 | .transactions | |
167 | .iter() | |
69cf5c9e | 168 | .position(|tx| tx.tx_id == tx_id + 1); |
c99b9462 PC |
169 | debug_assert!(tx != None); |
170 | if let Some(idx) = tx { | |
171 | let _ = self.transactions.remove(idx); | |
172 | } | |
173 | } | |
174 | ||
e2dbdd7f SS |
175 | pub fn get_tx(&mut self, tx_id: u64) -> Option<&mut IKETransaction> { |
176 | for tx in &mut self.transactions { | |
177 | if tx.tx_id == tx_id + 1 { | |
178 | return Some(tx); | |
179 | } | |
180 | } | |
181 | return None; | |
182 | } | |
183 | ||
184 | pub fn new_tx(&mut self) -> IKETransaction { | |
185 | let mut tx = IKETransaction::new(); | |
186 | self.tx_id += 1; | |
187 | tx.tx_id = self.tx_id; | |
188 | return tx; | |
189 | } | |
190 | ||
c99b9462 | 191 | /// Set an event. The event is set on the most recent transaction. |
e2dbdd7f | 192 | pub fn set_event(&mut self, event: IkeEvent) { |
c99b9462 PC |
193 | if let Some(tx) = self.transactions.last_mut() { |
194 | let ev = event as u8; | |
195 | core::sc_app_layer_decoder_events_set_event_raw(&mut tx.events, ev); | |
f90733fe | 196 | } else { |
e2dbdd7f SS |
197 | SCLogDebug!( |
198 | "IKE: trying to set event {} on non-existing transaction", | |
199 | event as u32 | |
200 | ); | |
c99b9462 PC |
201 | } |
202 | } | |
203 | ||
e2dbdd7f SS |
204 | fn handle_input(&mut self, input: &[u8], direction: u8) -> AppLayerResult { |
205 | // We're not interested in empty requests. | |
206 | if input.len() == 0 { | |
207 | return AppLayerResult::ok(); | |
208 | } | |
209 | ||
210 | let mut current = input; | |
211 | match parse_isakmp_header(current) { | |
212 | Ok((rem, isakmp_header)) => { | |
213 | current = rem; | |
214 | ||
215 | if isakmp_header.maj_ver != 1 && isakmp_header.maj_ver != 2 { | |
216 | SCLogDebug!("Unsupported ISAKMP major_version"); | |
217 | return AppLayerResult::err(); | |
c99b9462 | 218 | } |
e2dbdd7f SS |
219 | |
220 | if isakmp_header.maj_ver == 1 { | |
221 | handle_ikev1(self, current, isakmp_header, direction); | |
222 | } else if isakmp_header.maj_ver == 2 { | |
223 | handle_ikev2(self, current, isakmp_header, direction); | |
224 | } else { | |
225 | return AppLayerResult::err(); | |
c99b9462 | 226 | } |
e2dbdd7f | 227 | return AppLayerResult::ok(); // todo either remove outer loop or check header length-field if we have completely read everything |
c99b9462 | 228 | } |
e2dbdd7f SS |
229 | Err(nom::Err::Incomplete(_)) => { |
230 | SCLogDebug!("Insufficient data while parsing IKE"); | |
231 | return AppLayerResult::err(); | |
c99b9462 | 232 | } |
e2dbdd7f SS |
233 | Err(_) => { |
234 | SCLogDebug!("Error while parsing IKE packet"); | |
235 | return AppLayerResult::err(); | |
c99b9462 PC |
236 | } |
237 | } | |
238 | } | |
c99b9462 | 239 | |
e2dbdd7f SS |
240 | fn tx_iterator( |
241 | &mut self, min_tx_id: u64, state: &mut u64, | |
242 | ) -> Option<(&IKETransaction, u64, bool)> { | |
243 | let mut index = *state as usize; | |
244 | let len = self.transactions.len(); | |
245 | ||
246 | while index < len { | |
247 | let tx = &self.transactions[index]; | |
248 | if tx.tx_id < min_tx_id + 1 { | |
249 | index += 1; | |
250 | continue; | |
251 | } | |
252 | *state = index as u64; | |
253 | ||
254 | return Some((tx, tx.tx_id - 1, (len - index) > 1)); | |
c99b9462 | 255 | } |
e2dbdd7f SS |
256 | |
257 | return None; | |
c99b9462 | 258 | } |
e2dbdd7f | 259 | } |
c99b9462 | 260 | |
e2dbdd7f SS |
261 | /// Probe to see if this input looks like a request or response. |
262 | fn probe(input: &[u8], direction: u8, rdir: *mut u8) -> bool { | |
263 | match parse_isakmp_header(input) { | |
264 | Ok((_, isakmp_header)) => { | |
265 | if isakmp_header.maj_ver == 1 { | |
266 | if isakmp_header.resp_spi == 0 && direction != STREAM_TOSERVER { | |
267 | unsafe { | |
268 | *rdir = STREAM_TOSERVER; | |
269 | } | |
270 | } | |
271 | return true; | |
272 | } else if isakmp_header.maj_ver == 2 { | |
273 | if isakmp_header.min_ver != 0 { | |
274 | SCLogDebug!( | |
275 | "ipsec_probe: could be ipsec, but with unsupported/invalid version {}.{}", | |
276 | isakmp_header.maj_ver, | |
277 | isakmp_header.min_ver | |
278 | ); | |
279 | return false; | |
280 | } | |
281 | if isakmp_header.exch_type < 34 || isakmp_header.exch_type > 37 { | |
282 | SCLogDebug!("ipsec_probe: could be ipsec, but with unsupported/invalid exchange type {}", | |
283 | isakmp_header.exch_type); | |
284 | return false; | |
285 | } | |
286 | if isakmp_header.length as usize != input.len() { | |
287 | SCLogDebug!("ipsec_probe: could be ipsec, but length does not match"); | |
288 | return false; | |
289 | } | |
290 | ||
291 | if isakmp_header.resp_spi == 0 && direction != STREAM_TOSERVER { | |
292 | unsafe { | |
293 | *rdir = STREAM_TOSERVER; | |
294 | } | |
295 | } | |
296 | return true; | |
297 | } | |
298 | ||
299 | return false; | |
083908f3 | 300 | } |
e2dbdd7f | 301 | Err(_) => return false, |
c99b9462 PC |
302 | } |
303 | } | |
304 | ||
e2dbdd7f SS |
305 | // C exports. |
306 | export_tx_get_detect_state!(rs_ike_tx_get_detect_state, IKETransaction); | |
307 | export_tx_set_detect_state!(rs_ike_tx_set_detect_state, IKETransaction); | |
308 | ||
309 | /// C entry point for a probing parser. | |
310 | #[no_mangle] | |
363b5f99 | 311 | pub unsafe extern "C" fn rs_ike_probing_parser( |
e2dbdd7f SS |
312 | _flow: *const Flow, direction: u8, input: *const u8, input_len: u32, rdir: *mut u8, |
313 | ) -> AppProto { | |
314 | if input_len < 28 { | |
315 | // at least the ISAKMP_HEADER must be there, not ALPROTO_UNKNOWN because over UDP | |
363b5f99 | 316 | return ALPROTO_FAILED; |
e2dbdd7f SS |
317 | } |
318 | ||
922a453d | 319 | if !input.is_null() { |
e2dbdd7f SS |
320 | let slice = build_slice!(input, input_len as usize); |
321 | if probe(slice, direction, rdir) { | |
363b5f99 | 322 | return ALPROTO_IKE ; |
e2dbdd7f | 323 | } |
c99b9462 | 324 | } |
363b5f99 | 325 | return ALPROTO_FAILED; |
c99b9462 PC |
326 | } |
327 | ||
c99b9462 | 328 | #[no_mangle] |
e2dbdd7f SS |
329 | pub extern "C" fn rs_ike_state_new( |
330 | _orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto, | |
331 | ) -> *mut std::os::raw::c_void { | |
332 | let state = IKEState::default(); | |
c99b9462 | 333 | let boxed = Box::new(state); |
53413f2d | 334 | return Box::into_raw(boxed) as *mut _; |
c99b9462 PC |
335 | } |
336 | ||
c99b9462 | 337 | #[no_mangle] |
363b5f99 | 338 | pub unsafe extern "C" fn rs_ike_state_free(state: *mut std::os::raw::c_void) { |
c99b9462 | 339 | // Just unbox... |
363b5f99 | 340 | std::mem::drop(Box::from_raw(state as *mut IKEState)); |
c99b9462 PC |
341 | } |
342 | ||
343 | #[no_mangle] | |
363b5f99 | 344 | pub unsafe extern "C" fn rs_ike_state_tx_free(state: *mut std::os::raw::c_void, tx_id: u64) { |
e2dbdd7f SS |
345 | let state = cast_pointer!(state, IKEState); |
346 | state.free_tx(tx_id); | |
c99b9462 PC |
347 | } |
348 | ||
349 | #[no_mangle] | |
363b5f99 | 350 | pub unsafe extern "C" fn rs_ike_parse_request( |
e2dbdd7f SS |
351 | _flow: *const Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void, |
352 | input: *const u8, input_len: u32, _data: *const std::os::raw::c_void, _flags: u8, | |
353 | ) -> AppLayerResult { | |
354 | let state = cast_pointer!(state, IKEState); | |
355 | let buf = build_slice!(input, input_len as usize); | |
356 | ||
357 | return state.handle_input(buf, STREAM_TOSERVER); | |
c99b9462 PC |
358 | } |
359 | ||
360 | #[no_mangle] | |
363b5f99 | 361 | pub unsafe extern "C" fn rs_ike_parse_response( |
e2dbdd7f SS |
362 | _flow: *const Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void, |
363 | input: *const u8, input_len: u32, _data: *const std::os::raw::c_void, _flags: u8, | |
364 | ) -> AppLayerResult { | |
365 | let state = cast_pointer!(state, IKEState); | |
366 | let buf = build_slice!(input, input_len as usize); | |
367 | return state.handle_input(buf, STREAM_TOCLIENT); | |
c99b9462 PC |
368 | } |
369 | ||
370 | #[no_mangle] | |
363b5f99 | 371 | pub unsafe extern "C" fn rs_ike_state_get_tx( |
e2dbdd7f SS |
372 | state: *mut std::os::raw::c_void, tx_id: u64, |
373 | ) -> *mut std::os::raw::c_void { | |
374 | let state = cast_pointer!(state, IKEState); | |
375 | match state.get_tx(tx_id) { | |
376 | Some(tx) => { | |
53413f2d | 377 | return tx as *const _ as *mut _; |
e2dbdd7f SS |
378 | } |
379 | None => { | |
380 | return std::ptr::null_mut(); | |
381 | } | |
382 | } | |
c99b9462 PC |
383 | } |
384 | ||
385 | #[no_mangle] | |
363b5f99 | 386 | pub unsafe extern "C" fn rs_ike_state_get_tx_count(state: *mut std::os::raw::c_void) -> u64 { |
e2dbdd7f SS |
387 | let state = cast_pointer!(state, IKEState); |
388 | return state.tx_id; | |
c99b9462 PC |
389 | } |
390 | ||
c99b9462 | 391 | #[no_mangle] |
e2dbdd7f SS |
392 | pub extern "C" fn rs_ike_state_progress_completion_status(_direction: u8) -> std::os::raw::c_int { |
393 | // This parser uses 1 to signal transaction completion status. | |
ecdf9f6b | 394 | return 1; |
395 | } | |
396 | ||
397 | #[no_mangle] | |
e2dbdd7f SS |
398 | pub extern "C" fn rs_ike_tx_get_alstate_progress( |
399 | _tx: *mut std::os::raw::c_void, _direction: u8, | |
400 | ) -> std::os::raw::c_int { | |
401 | return 1; | |
c99b9462 PC |
402 | } |
403 | ||
c99b9462 | 404 | #[no_mangle] |
363b5f99 | 405 | pub unsafe extern "C" fn rs_ike_tx_get_logged( |
e2dbdd7f SS |
406 | _state: *mut std::os::raw::c_void, tx: *mut std::os::raw::c_void, |
407 | ) -> u32 { | |
408 | let tx = cast_pointer!(tx, IKETransaction); | |
409 | return tx.logged.get(); | |
c99b9462 PC |
410 | } |
411 | ||
412 | #[no_mangle] | |
363b5f99 | 413 | pub unsafe extern "C" fn rs_ike_tx_set_logged( |
e2dbdd7f SS |
414 | _state: *mut std::os::raw::c_void, tx: *mut std::os::raw::c_void, logged: u32, |
415 | ) { | |
416 | let tx = cast_pointer!(tx, IKETransaction); | |
417 | tx.logged.set(logged); | |
c99b9462 PC |
418 | } |
419 | ||
c99b9462 | 420 | #[no_mangle] |
363b5f99 | 421 | pub unsafe extern "C" fn rs_ike_state_get_events( |
e2dbdd7f SS |
422 | tx: *mut std::os::raw::c_void, |
423 | ) -> *mut core::AppLayerDecoderEvents { | |
ecdf9f6b | 424 | let tx = cast_pointer!(tx, IKETransaction); |
d568e7fa | 425 | return tx.events; |
c99b9462 PC |
426 | } |
427 | ||
ecdf9f6b | 428 | static mut ALPROTO_IKE : AppProto = ALPROTO_UNKNOWN; |
c99b9462 PC |
429 | |
430 | #[no_mangle] | |
363b5f99 | 431 | pub unsafe extern "C" fn rs_ike_state_get_tx_iterator( |
e2dbdd7f SS |
432 | _ipproto: u8, _alproto: AppProto, state: *mut std::os::raw::c_void, min_tx_id: u64, |
433 | _max_tx_id: u64, istate: &mut u64, | |
434 | ) -> applayer::AppLayerGetTxIterTuple { | |
435 | let state = cast_pointer!(state, IKEState); | |
436 | match state.tx_iterator(min_tx_id, istate) { | |
437 | Some((tx, out_tx_id, has_next)) => { | |
53413f2d | 438 | let c_tx = tx as *const _ as *mut _; |
e2dbdd7f SS |
439 | let ires = applayer::AppLayerGetTxIterTuple::with_values(c_tx, out_tx_id, has_next); |
440 | return ires; | |
441 | } | |
442 | None => { | |
443 | return applayer::AppLayerGetTxIterTuple::not_found(); | |
444 | } | |
c99b9462 PC |
445 | } |
446 | } | |
447 | ||
e2dbdd7f SS |
448 | // Parser name as a C style string. |
449 | const PARSER_NAME: &'static [u8] = b"ike\0"; | |
450 | const PARSER_ALIAS: &'static [u8] = b"ikev2\0"; | |
e0f75157 | 451 | |
e2dbdd7f | 452 | export_tx_data_get!(rs_ike_get_tx_data, IKETransaction); |
c99b9462 PC |
453 | |
454 | #[no_mangle] | |
e2dbdd7f | 455 | pub unsafe extern "C" fn rs_ike_register_parser() { |
c99b9462 PC |
456 | let default_port = CString::new("500").unwrap(); |
457 | let parser = RustParser { | |
fb016416 JL |
458 | name : PARSER_NAME.as_ptr() as *const std::os::raw::c_char, |
459 | default_port : default_port.as_ptr(), | |
460 | ipproto : core::IPPROTO_UDP, | |
ecdf9f6b | 461 | probe_ts : Some(rs_ike_probing_parser), |
462 | probe_tc : Some(rs_ike_probing_parser), | |
fb016416 JL |
463 | min_depth : 0, |
464 | max_depth : 16, | |
ecdf9f6b | 465 | state_new : rs_ike_state_new, |
466 | state_free : rs_ike_state_free, | |
467 | tx_free : rs_ike_state_tx_free, | |
468 | parse_ts : rs_ike_parse_request, | |
469 | parse_tc : rs_ike_parse_response, | |
470 | get_tx_count : rs_ike_state_get_tx_count, | |
471 | get_tx : rs_ike_state_get_tx, | |
efc9a7a3 VJ |
472 | tx_comp_st_ts : 1, |
473 | tx_comp_st_tc : 1, | |
ecdf9f6b | 474 | tx_get_progress : rs_ike_tx_get_alstate_progress, |
e2dbdd7f SS |
475 | get_de_state : rs_ike_tx_get_detect_state, |
476 | set_de_state : rs_ike_tx_set_detect_state, | |
ecdf9f6b | 477 | get_events : Some(rs_ike_state_get_events), |
71679c6a JI |
478 | get_eventinfo : Some(IkeEvent::get_event_info), |
479 | get_eventinfo_byid : Some(IkeEvent::get_event_info_by_id), | |
fb016416 JL |
480 | localstorage_new : None, |
481 | localstorage_free : None, | |
fb016416 JL |
482 | get_files : None, |
483 | get_tx_iterator : None, | |
ecdf9f6b | 484 | get_tx_data : rs_ike_get_tx_data, |
5665fc83 | 485 | apply_tx_config : None, |
3036ec4d | 486 | flags : APP_LAYER_PARSER_OPT_UNIDIR_TXS, |
4da0d9bd | 487 | truncate : None, |
c99b9462 PC |
488 | }; |
489 | ||
490 | let ip_proto_str = CString::new("udp").unwrap(); | |
e2dbdd7f | 491 | |
c99b9462 PC |
492 | if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { |
493 | let alproto = AppLayerRegisterProtocolDetection(&parser, 1); | |
ecdf9f6b | 494 | ALPROTO_IKE = alproto; |
c99b9462 PC |
495 | if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { |
496 | let _ = AppLayerRegisterParser(&parser, alproto); | |
497 | } | |
e2dbdd7f SS |
498 | |
499 | AppLayerRegisterParserAlias( | |
500 | PARSER_NAME.as_ptr() as *const std::os::raw::c_char, | |
501 | PARSER_ALIAS.as_ptr() as *const std::os::raw::c_char, | |
502 | ); | |
503 | SCLogDebug!("Rust IKE parser registered."); | |
c99b9462 | 504 | } else { |
ecdf9f6b | 505 | SCLogDebug!("Protocol detector and parser disabled for IKE."); |
c99b9462 PC |
506 | } |
507 | } |