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