]> git.ipfire.org Git - people/ms/suricata.git/blame - rust/src/rfb/rfb.rs
app-layer: don't check tx detect flags if detect is disabled
[people/ms/suricata.git] / rust / src / rfb / rfb.rs
CommitLineData
1c8943de
FH
1/* Copyright (C) 2020 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// Author: Frank Honza <frank.honza@dcso.de>
19
20use std;
21use std::ffi::CString;
22use std::mem::transmute;
23use crate::core::{self, ALPROTO_UNKNOWN, AppProto, Flow, IPPROTO_TCP};
1c8943de
FH
24use crate::applayer;
25use crate::applayer::*;
26use nom;
27use super::parser;
28
29static mut ALPROTO_RFB: AppProto = ALPROTO_UNKNOWN;
30
31pub struct RFBTransaction {
32 tx_id: u64,
33 pub complete: bool,
34 pub chosen_security_type: Option<u32>,
35
36 pub tc_server_protocol_version: Option<parser::ProtocolVersion>,
37 pub ts_client_protocol_version: Option<parser::ProtocolVersion>,
38 pub tc_supported_security_types: Option<parser::SupportedSecurityTypes>,
39 pub ts_security_type_selection: Option<parser::SecurityTypeSelection>,
40 pub tc_server_security_type: Option<parser::ServerSecurityType>,
41 pub tc_vnc_challenge: Option<parser::VncAuth>,
42 pub ts_vnc_response: Option<parser::VncAuth>,
43 pub ts_client_init: Option<parser::ClientInit>,
44 pub tc_security_result: Option<parser::SecurityResult>,
45 pub tc_failure_reason: Option<parser::FailureReason>,
46 pub tc_server_init: Option<parser::ServerInit>,
47
1c8943de
FH
48 de_state: Option<*mut core::DetectEngineState>,
49 events: *mut core::AppLayerDecoderEvents,
5afe4835 50 tx_data: applayer::AppLayerTxData,
1c8943de
FH
51}
52
53impl RFBTransaction {
54 pub fn new() -> RFBTransaction {
55 RFBTransaction {
56 tx_id: 0,
57 complete: false,
58 chosen_security_type: None,
59
60 tc_server_protocol_version: None,
61 ts_client_protocol_version: None,
62 tc_supported_security_types: None,
63 ts_security_type_selection: None,
64 tc_server_security_type: None,
65 tc_vnc_challenge: None,
66 ts_vnc_response: None,
67 ts_client_init: None,
68 tc_security_result: None,
69 tc_failure_reason: None,
70 tc_server_init: None,
71
1c8943de
FH
72 de_state: None,
73 events: std::ptr::null_mut(),
5afe4835 74 tx_data: applayer::AppLayerTxData::new(),
1c8943de
FH
75 }
76 }
77
78 pub fn free(&mut self) {
79 if self.events != std::ptr::null_mut() {
80 core::sc_app_layer_decoder_events_free_events(&mut self.events);
81 }
82 if let Some(state) = self.de_state {
83 core::sc_detect_engine_state_free(state);
84 }
85 }
86}
87
88impl Drop for RFBTransaction {
89 fn drop(&mut self) {
90 self.free();
91 }
92}
93
94pub struct RFBState {
95 tx_id: u64,
96 transactions: Vec<RFBTransaction>,
97 state: parser::RFBGlobalState
98}
99
100impl RFBState {
101 pub fn new() -> Self {
102 Self {
103 tx_id: 0,
104 transactions: Vec::new(),
105 state: parser::RFBGlobalState::TCServerProtocolVersion
106 }
107 }
108
109 // Free a transaction by ID.
110 fn free_tx(&mut self, tx_id: u64) {
111 let len = self.transactions.len();
112 let mut found = false;
113 let mut index = 0;
114 for i in 0..len {
115 let tx = &self.transactions[i];
116 if tx.tx_id == tx_id + 1 {
117 found = true;
118 index = i;
119 break;
120 }
121 }
122 if found {
123 self.transactions.remove(index);
124 }
125 }
126
127 pub fn get_tx(&mut self, tx_id: u64) -> Option<&RFBTransaction> {
128 for tx in &mut self.transactions {
129 if tx.tx_id == tx_id + 1 {
130 return Some(tx);
131 }
132 }
133 return None;
134 }
135
136 fn new_tx(&mut self) -> RFBTransaction {
137 let mut tx = RFBTransaction::new();
138 self.tx_id += 1;
139 tx.tx_id = self.tx_id;
140 return tx;
141 }
142
143 fn get_current_tx(&mut self) -> Option<&mut RFBTransaction> {
144 for tx in &mut self.transactions {
145 if tx.tx_id == self.tx_id {
146 return Some(tx);
147 }
148 }
149 return None;
150 }
151
152 fn parse_request(&mut self, input: &[u8]) -> AppLayerResult {
153 // We're not interested in empty requests.
154 if input.len() == 0 {
155 return AppLayerResult::ok();
156 }
157
158 let mut current = input;
bbe9137f 159 let mut consumed = 0;
1c8943de
FH
160 SCLogDebug!("request_state {}, input_len {}", self.state, input.len());
161 loop {
162 if current.len() == 0 {
163 return AppLayerResult::ok();
164 }
165 match self.state {
166 parser::RFBGlobalState::TSClientProtocolVersion => {
167 match parser::parse_protocol_version(current) {
168 Ok((rem, request)) => {
bbe9137f 169 consumed += current.len() - rem.len();
1c8943de 170 current = rem;
bbe9137f 171
1c8943de
FH
172 if request.major == "003" && request.minor == "003" {
173 // in version 3.3 the server decided security type
174 self.state = parser::RFBGlobalState::TCServerSecurityType;
175 } else {
176 self.state = parser::RFBGlobalState::TCSupportedSecurityTypes;
177 }
178
26123e05
SS
179 if let Some(current_transaction) = self.get_current_tx() {
180 current_transaction.ts_client_protocol_version = Some(request);
181 } else {
182 return AppLayerResult::err();
1c8943de
FH
183 }
184 }
bbe9137f 185 Err(nom::Err::Incomplete(_)) => {
186 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
187 }
188 Err(_) => {
189 return AppLayerResult::err();
190 }
191 }
192 }
193 parser::RFBGlobalState::TSSecurityTypeSelection => {
194 match parser::parse_security_type_selection(current) {
195 Ok((rem, request)) => {
bbe9137f 196 consumed += current.len() - rem.len();
1c8943de
FH
197 current = rem;
198
199 let chosen_security_type = request.security_type;
200 match chosen_security_type {
201 2 => self.state = parser::RFBGlobalState::TCVncChallenge,
202 1 => self.state = parser::RFBGlobalState::TSClientInit,
203 _ => return AppLayerResult::err(),
204 }
205
26123e05
SS
206 if let Some(current_transaction) = self.get_current_tx() {
207 current_transaction.ts_security_type_selection = Some(request);
208 current_transaction.chosen_security_type = Some(chosen_security_type as u32);
209 } else {
210 return AppLayerResult::err();
1c8943de
FH
211 }
212 }
bbe9137f 213 Err(nom::Err::Incomplete(_)) => {
214 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
215 }
216 Err(_) => {
217 return AppLayerResult::err();
218 }
219 }
220 }
221 parser::RFBGlobalState::TSVncResponse => {
222 match parser::parse_vnc_auth(current) {
223 Ok((rem, request)) => {
bbe9137f 224 consumed += current.len() - rem.len();
1c8943de
FH
225 current = rem;
226
227 self.state = parser::RFBGlobalState::TCSecurityResult;
228
26123e05
SS
229 if let Some(current_transaction) = self.get_current_tx() {
230 current_transaction.ts_vnc_response = Some(request);
231 } else {
232 return AppLayerResult::err();
1c8943de
FH
233 }
234 }
bbe9137f 235 Err(nom::Err::Incomplete(_)) => {
236 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
237 }
238 Err(_) => {
239 return AppLayerResult::err();
240 }
241 }
242 }
243 parser::RFBGlobalState::TSClientInit => {
244 match parser::parse_client_init(current) {
245 Ok((rem, request)) => {
bbe9137f 246 consumed += current.len() - rem.len();
1c8943de 247 current = rem;
bbe9137f 248
1c8943de
FH
249 self.state = parser::RFBGlobalState::TCServerInit;
250
26123e05
SS
251 if let Some(current_transaction) = self.get_current_tx() {
252 current_transaction.ts_client_init = Some(request);
253 } else {
254 return AppLayerResult::err();
1c8943de
FH
255 }
256 }
bbe9137f 257 Err(nom::Err::Incomplete(_)) => {
258 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
259 }
260 Err(_) => {
261 return AppLayerResult::err();
262 }
263 }
264 }
265 parser::RFBGlobalState::Message => {
266 //todo implement RFB messages, for now we stop here
267 return AppLayerResult::err();
268 }
269 parser::RFBGlobalState::TCServerProtocolVersion => {
270 SCLogDebug!("Reversed traffic, expected response.");
271 return AppLayerResult::err();
272 }
273 _ => {
274 SCLogDebug!("Invalid state for request {}", self.state);
275 current = b"";
276 }
277 }
278 }
279 }
280
281 fn parse_response(&mut self, input: &[u8]) -> AppLayerResult {
282 // We're not interested in empty responses.
283 if input.len() == 0 {
284 return AppLayerResult::ok();
285 }
286
287 let mut current = input;
bbe9137f 288 let mut consumed = 0;
1c8943de
FH
289 SCLogDebug!("response_state {}, response_len {}", self.state, input.len());
290 loop {
291 if current.len() == 0 {
292 return AppLayerResult::ok();
293 }
294 match self.state {
295 parser::RFBGlobalState::TCServerProtocolVersion => {
296 match parser::parse_protocol_version(current) {
297 Ok((rem, request)) => {
bbe9137f 298 consumed += current.len() - rem.len();
1c8943de 299 current = rem;
bbe9137f 300
1c8943de
FH
301 self.state = parser::RFBGlobalState::TSClientProtocolVersion;
302 let tx = self.new_tx();
303 self.transactions.push(tx);
304
26123e05
SS
305 if let Some(current_transaction) = self.get_current_tx() {
306 current_transaction.tc_server_protocol_version = Some(request);
307 } else {
308 return AppLayerResult::err();
1c8943de
FH
309 }
310 }
bbe9137f 311 Err(nom::Err::Incomplete(_)) => {
312 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
313 }
314 Err(_) => {
315 return AppLayerResult::err();
316 }
317 }
318 }
319 parser::RFBGlobalState::TCSupportedSecurityTypes => {
320 match parser::parse_supported_security_types(current) {
321 Ok((rem, request)) => {
bbe9137f 322 consumed += current.len() - rem.len();
1c8943de 323 current = rem;
bbe9137f 324
1c8943de
FH
325 SCLogDebug!(
326 "supported_security_types: {}, types: {}", request.number_of_types,
327 request.types.iter().map(ToString::to_string).map(|v| v + " ").collect::<String>()
328 );
329
330 self.state = parser::RFBGlobalState::TSSecurityTypeSelection;
331 if request.number_of_types == 0 {
332 self.state = parser::RFBGlobalState::TCFailureReason;
333 }
334
26123e05
SS
335 if let Some(current_transaction) = self.get_current_tx() {
336 current_transaction.tc_supported_security_types = Some(request);
337 } else {
338 return AppLayerResult::err();
1c8943de
FH
339 }
340 }
bbe9137f 341 Err(nom::Err::Incomplete(_)) => {
342 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
343 }
344 Err(_) => {
345 return AppLayerResult::err();
346 }
347 }
348 }
349 parser::RFBGlobalState::TCServerSecurityType => {
350 // In RFB 3.3, the server decides the authentication type
351 match parser::parse_server_security_type(current) {
352 Ok((rem, request)) => {
bbe9137f 353 consumed += current.len() - rem.len();
1c8943de 354 current = rem;
bbe9137f 355
1c8943de
FH
356 let chosen_security_type = request.security_type;
357 SCLogDebug!("chosen_security_type: {}", chosen_security_type);
358 match chosen_security_type {
359 0 => self.state = parser::RFBGlobalState::TCFailureReason,
360 1 => self.state = parser::RFBGlobalState::TSClientInit,
361 2 => self.state = parser::RFBGlobalState::TCVncChallenge,
362 _ => {
363 // TODO Event unknown security type
364 return AppLayerResult::err();
365 }
366 }
367
26123e05
SS
368 if let Some(current_transaction) = self.get_current_tx() {
369 current_transaction.tc_server_security_type = Some(request);
370 current_transaction.chosen_security_type = Some(chosen_security_type);
371 } else {
372 return AppLayerResult::err();
1c8943de
FH
373 }
374 }
bbe9137f 375 Err(nom::Err::Incomplete(_)) => {
376 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
377 }
378 Err(_) => {
379 return AppLayerResult::err();
380 }
381 }
382 }
383 parser::RFBGlobalState::TCVncChallenge => {
384 match parser::parse_vnc_auth(current) {
385 Ok((rem, request)) => {
bbe9137f 386 consumed += current.len() - rem.len();
1c8943de
FH
387 current = rem;
388
389 self.state = parser::RFBGlobalState::TSVncResponse;
390
26123e05
SS
391 if let Some(current_transaction) = self.get_current_tx() {
392 current_transaction.tc_vnc_challenge = Some(request);
393 } else {
394 return AppLayerResult::err();
1c8943de
FH
395 }
396 }
bbe9137f 397 Err(nom::Err::Incomplete(_)) => {
398 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
399 }
400 Err(_) => {
401 return AppLayerResult::err();
402 }
403 }
404 }
405 parser::RFBGlobalState::TCSecurityResult => {
406 match parser::parse_security_result(current) {
407 Ok((rem, request)) => {
bbe9137f 408 consumed += current.len() - rem.len();
1c8943de
FH
409 current = rem;
410
411 if request.status == 0 {
412 self.state = parser::RFBGlobalState::TSClientInit;
413
26123e05
SS
414 if let Some(current_transaction) = self.get_current_tx() {
415 current_transaction.tc_security_result = Some(request);
416 } else {
417 return AppLayerResult::err();
1c8943de
FH
418 }
419 } else if request.status == 1 {
420 self.state = parser::RFBGlobalState::TCFailureReason;
421 } else {
422 // TODO: Event: unknown security result value
423 }
424 }
bbe9137f 425 Err(nom::Err::Incomplete(_)) => {
426 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
427 }
428 Err(_) => {
429 return AppLayerResult::err();
430 }
431 }
432 }
433 parser::RFBGlobalState::TCFailureReason => {
434 match parser::parse_failure_reason(current) {
435 Ok((_rem, request)) => {
26123e05
SS
436 if let Some(current_transaction) = self.get_current_tx() {
437 current_transaction.tc_failure_reason = Some(request);
438 } else {
439 return AppLayerResult::err();
1c8943de
FH
440 }
441 return AppLayerResult::err();
442 }
bbe9137f 443 Err(nom::Err::Incomplete(_)) => {
444 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
445 }
446 Err(_) => {
447 return AppLayerResult::err();
448 }
449 }
450 }
451 parser::RFBGlobalState::TCServerInit => {
452 match parser::parse_server_init(current) {
453 Ok((rem, request)) => {
bbe9137f 454 consumed += current.len() - rem.len();
1c8943de 455 current = rem;
bbe9137f 456
1c8943de
FH
457 self.state = parser::RFBGlobalState::Message;
458
26123e05
SS
459 if let Some(current_transaction) = self.get_current_tx() {
460 current_transaction.tc_server_init = Some(request);
461 // connection initialization is complete and parsed
462 current_transaction.complete = true;
463 } else {
464 return AppLayerResult::err();
1c8943de
FH
465 }
466 }
bbe9137f 467 Err(nom::Err::Incomplete(_)) => {
468 return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32);
1c8943de
FH
469 }
470 Err(_) => {
471 return AppLayerResult::err();
472 }
473 }
474 }
475 parser::RFBGlobalState::Message => {
476 //todo implement RFB messages, for now we stop here
477 return AppLayerResult::err();
478 }
479 _ => {
480 SCLogDebug!("Invalid state for response");
481 return AppLayerResult::err();
482 }
483 }
484 }
485 }
486
487 fn tx_iterator(
488 &mut self,
489 min_tx_id: u64,
490 state: &mut u64,
491 ) -> Option<(&RFBTransaction, u64, bool)> {
492 let mut index = *state as usize;
493 let len = self.transactions.len();
494
495 while index < len {
496 let tx = &self.transactions[index];
497 if tx.tx_id < min_tx_id + 1 {
498 index += 1;
499 continue;
500 }
501 *state = index as u64;
502 return Some((tx, tx.tx_id - 1, (len - index) > 1));
503 }
504
505 return None;
506 }
507}
508
509// C exports.
510
511export_tx_get_detect_state!(
512 rs_rfb_tx_get_detect_state,
513 RFBTransaction
514);
515export_tx_set_detect_state!(
516 rs_rfb_tx_set_detect_state,
517 RFBTransaction
518);
519
520#[no_mangle]
547d6c2d 521pub extern "C" fn rs_rfb_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void {
1c8943de
FH
522 let state = RFBState::new();
523 let boxed = Box::new(state);
524 return unsafe { transmute(boxed) };
525}
526
527#[no_mangle]
528pub extern "C" fn rs_rfb_state_free(state: *mut std::os::raw::c_void) {
529 // Just unbox...
530 let _drop: Box<RFBState> = unsafe { transmute(state) };
531}
532
533#[no_mangle]
534pub extern "C" fn rs_rfb_state_tx_free(
535 state: *mut std::os::raw::c_void,
536 tx_id: u64,
537) {
538 let state = cast_pointer!(state, RFBState);
539 state.free_tx(tx_id);
540}
541
542#[no_mangle]
543pub extern "C" fn rs_rfb_parse_request(
544 _flow: *const Flow,
545 state: *mut std::os::raw::c_void,
546 _pstate: *mut std::os::raw::c_void,
547 input: *const u8,
548 input_len: u32,
549 _data: *const std::os::raw::c_void,
550 _flags: u8,
551) -> AppLayerResult {
552 let state = cast_pointer!(state, RFBState);
553 let buf = build_slice!(input, input_len as usize);
554 return state.parse_request(buf);
555}
556
557#[no_mangle]
558pub extern "C" fn rs_rfb_parse_response(
559 _flow: *const Flow,
560 state: *mut std::os::raw::c_void,
561 _pstate: *mut std::os::raw::c_void,
562 input: *const u8,
563 input_len: u32,
564 _data: *const std::os::raw::c_void,
565 _flags: u8,
566) -> AppLayerResult {
567 let state = cast_pointer!(state, RFBState);
568 let buf = build_slice!(input, input_len as usize);
569 return state.parse_response(buf);
570}
571
572#[no_mangle]
573pub extern "C" fn rs_rfb_state_get_tx(
574 state: *mut std::os::raw::c_void,
575 tx_id: u64,
576) -> *mut std::os::raw::c_void {
577 let state = cast_pointer!(state, RFBState);
578 match state.get_tx(tx_id) {
579 Some(tx) => {
580 return unsafe { transmute(tx) };
581 }
582 None => {
583 return std::ptr::null_mut();
584 }
585 }
586}
587
588#[no_mangle]
589pub extern "C" fn rs_rfb_state_get_tx_count(
590 state: *mut std::os::raw::c_void,
591) -> u64 {
592 let state = cast_pointer!(state, RFBState);
593 return state.tx_id;
594}
595
596#[no_mangle]
597pub extern "C" fn rs_rfb_state_progress_completion_status(
598 _direction: u8,
599) -> std::os::raw::c_int {
600 // This parser uses 1 to signal transaction completion status.
601 return 1;
602}
603
604#[no_mangle]
605pub extern "C" fn rs_rfb_tx_get_alstate_progress(
606 tx: *mut std::os::raw::c_void,
607 _direction: u8,
608) -> std::os::raw::c_int {
609 let tx = cast_pointer!(tx, RFBTransaction);
610 if tx.complete {
611 return 1;
612 }
613 return 0;
614}
615
1c8943de
FH
616#[no_mangle]
617pub extern "C" fn rs_rfb_state_get_events(
618 tx: *mut std::os::raw::c_void
619) -> *mut core::AppLayerDecoderEvents {
620 let tx = cast_pointer!(tx, RFBTransaction);
621 return tx.events;
622}
623
624#[no_mangle]
625pub extern "C" fn rs_rfb_state_get_event_info(
626 _event_name: *const std::os::raw::c_char,
627 _event_id: *mut std::os::raw::c_int,
628 _event_type: *mut core::AppLayerEventType,
629) -> std::os::raw::c_int {
630 return -1;
631}
632
633#[no_mangle]
634pub extern "C" fn rs_rfb_state_get_event_info_by_id(_event_id: std::os::raw::c_int,
635 _event_name: *mut *const std::os::raw::c_char,
636 _event_type: *mut core::AppLayerEventType
637) -> i8 {
638 return -1;
639}
640#[no_mangle]
641pub extern "C" fn rs_rfb_state_get_tx_iterator(
642 _ipproto: u8,
643 _alproto: AppProto,
644 state: *mut std::os::raw::c_void,
645 min_tx_id: u64,
646 _max_tx_id: u64,
647 istate: &mut u64,
648) -> applayer::AppLayerGetTxIterTuple {
649 let state = cast_pointer!(state, RFBState);
650 match state.tx_iterator(min_tx_id, istate) {
651 Some((tx, out_tx_id, has_next)) => {
652 let c_tx = unsafe { transmute(tx) };
653 let ires = applayer::AppLayerGetTxIterTuple::with_values(
654 c_tx,
655 out_tx_id,
656 has_next,
657 );
658 return ires;
659 }
660 None => {
661 return applayer::AppLayerGetTxIterTuple::not_found();
662 }
663 }
664}
665
666// Parser name as a C style string.
667const PARSER_NAME: &'static [u8] = b"rfb\0";
668
5afe4835 669export_tx_data_get!(rs_rfb_get_tx_data, RFBTransaction);
1c8943de
FH
670
671#[no_mangle]
672pub unsafe extern "C" fn rs_rfb_register_parser() {
673 let default_port = CString::new("[5900]").unwrap();
674 let parser = RustParser {
675 name: PARSER_NAME.as_ptr() as *const std::os::raw::c_char,
676 default_port: default_port.as_ptr(),
677 ipproto: IPPROTO_TCP,
678 probe_ts: None,
679 probe_tc: None,
680 min_depth: 0,
681 max_depth: 16,
682 state_new: rs_rfb_state_new,
683 state_free: rs_rfb_state_free,
684 tx_free: rs_rfb_state_tx_free,
685 parse_ts: rs_rfb_parse_request,
686 parse_tc: rs_rfb_parse_response,
687 get_tx_count: rs_rfb_state_get_tx_count,
688 get_tx: rs_rfb_state_get_tx,
689 tx_get_comp_st: rs_rfb_state_progress_completion_status,
690 tx_get_progress: rs_rfb_tx_get_alstate_progress,
1c8943de
FH
691 get_de_state: rs_rfb_tx_get_detect_state,
692 set_de_state: rs_rfb_tx_set_detect_state,
693 get_events: Some(rs_rfb_state_get_events),
694 get_eventinfo: Some(rs_rfb_state_get_event_info),
695 get_eventinfo_byid : Some(rs_rfb_state_get_event_info_by_id),
696 localstorage_new: None,
697 localstorage_free: None,
1c8943de
FH
698 get_files: None,
699 get_tx_iterator: Some(rs_rfb_state_get_tx_iterator),
c94a5e63 700 get_tx_data: rs_rfb_get_tx_data,
5665fc83 701 apply_tx_config: None,
53aa967e 702 flags: 0,
1c8943de
FH
703 };
704
705 let ip_proto_str = CString::new("tcp").unwrap();
706
707 if AppLayerProtoDetectConfProtoDetectionEnabled(
708 ip_proto_str.as_ptr(),
709 parser.name,
710 ) != 0
711 {
712 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
713 ALPROTO_RFB = alproto;
714 if AppLayerParserConfParserEnabled(
715 ip_proto_str.as_ptr(),
716 parser.name,
717 ) != 0
718 {
719 let _ = AppLayerRegisterParser(&parser, alproto);
720 }
721 SCLogDebug!("Rust rfb parser registered.");
722 } else {
723 SCLogDebug!("Protocol detector and parser disabled for RFB.");
724 }
725}