/src/suricata/rust/src/frames.rs
Line | Count | Source |
1 | | /* Copyright (C) 2017-2021 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 | | //! Module for bindings to the Suricata C frame API. |
19 | | |
20 | | use crate::applayer::StreamSlice; |
21 | | #[cfg(not(test))] |
22 | | use crate::applayer::StreamSliceRust; |
23 | | #[cfg(not(test))] |
24 | | use crate::core::STREAM_TOSERVER; |
25 | | use crate::direction::Direction; |
26 | | use crate::flow::Flow; |
27 | | |
28 | | #[cfg(not(test))] |
29 | | use std::os::raw::c_void; |
30 | | use suricata_sys::sys::{SCAppLayerFrameAddEventById, SCAppLayerFrameSetLengthById}; |
31 | | #[cfg(not(test))] |
32 | | use suricata_sys::sys::{SCAppLayerFrameNewByRelativeOffset, SCAppLayerFrameSetTxIdById}; |
33 | | |
34 | | pub struct Frame { |
35 | | pub id: i64, |
36 | | direction: Direction, |
37 | | } |
38 | | |
39 | | impl std::fmt::Debug for Frame { |
40 | 0 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
41 | 0 | write!(f, "frame: {}, direction: {}", self.id, self.direction) |
42 | 0 | } |
43 | | } |
44 | | |
45 | | impl Frame { |
46 | | #[cfg(not(test))] |
47 | | #[allow(clippy::not_unsafe_ptr_arg_deref)] |
48 | 24.7M | pub fn new( |
49 | 24.7M | flow: *mut Flow, stream_slice: &StreamSlice, frame_start: &[u8], frame_len: i64, |
50 | 24.7M | frame_type: u8, tx_id: Option<u64>, |
51 | 24.7M | ) -> Option<Self> { |
52 | 24.7M | let offset = frame_start.as_ptr() as usize - stream_slice.as_slice().as_ptr() as usize; |
53 | | SCLogDebug!( |
54 | | "offset {} stream_slice.len() {} frame_start.len() {}", |
55 | | offset, |
56 | | stream_slice.len(), |
57 | | frame_start.len() |
58 | | ); |
59 | 24.7M | let frame = unsafe { |
60 | 24.7M | SCAppLayerFrameNewByRelativeOffset( |
61 | 24.7M | flow, |
62 | 24.7M | stream_slice as *const _ as *const c_void, |
63 | 24.7M | offset as u32, |
64 | 24.7M | frame_len, |
65 | 24.7M | (stream_slice.flags() & STREAM_TOSERVER == 0).into(), |
66 | 24.7M | frame_type, |
67 | | ) |
68 | | }; |
69 | 24.7M | if !frame.is_null() { |
70 | 1.81M | let id = unsafe { (*frame).id }; |
71 | 1.81M | let r = Self { |
72 | 1.81M | id, |
73 | 1.81M | direction: Direction::from(stream_slice.flags()), |
74 | 1.81M | }; |
75 | 1.81M | if let Some(tx_id) = tx_id { |
76 | 256k | unsafe { |
77 | 256k | SCAppLayerFrameSetTxIdById(flow, r.direction(), id, tx_id); |
78 | 256k | }; |
79 | 1.55M | } |
80 | 1.81M | Some(r) |
81 | | } else { |
82 | 22.8M | None |
83 | | } |
84 | 24.7M | } |
85 | | |
86 | | /// A variation of `new` for use when running Rust unit tests as |
87 | | /// the C functions for building a frame are not available for |
88 | | /// linkage. |
89 | | #[cfg(test)] |
90 | | pub fn new( |
91 | | _flow: *const Flow, _stream_slice: &StreamSlice, _frame_start: &[u8], _frame_len: i64, |
92 | | _frame_type: u8, _tx_id: Option<u64>, |
93 | | ) -> Option<Self> { |
94 | | None |
95 | | } |
96 | | |
97 | | /// Conversion function to get the direction in the correct form for the |
98 | | /// C frame methods which takes direction as a u32 value of 0 or 1 rather |
99 | | /// than the flag value used internally by Frame. |
100 | 525k | fn direction(&self) -> i32 { |
101 | 525k | match self.direction { |
102 | 373k | Direction::ToServer => 0, |
103 | 152k | Direction::ToClient => 1, |
104 | | } |
105 | 525k | } |
106 | | |
107 | | #[allow(clippy::not_unsafe_ptr_arg_deref)] |
108 | 17.8k | pub fn set_len(&self, flow: *const Flow, len: i64) { |
109 | 17.8k | unsafe { |
110 | 17.8k | SCAppLayerFrameSetLengthById(flow, self.direction(), self.id, len); |
111 | 17.8k | }; |
112 | 17.8k | } |
113 | | |
114 | | #[cfg(not(test))] |
115 | | #[allow(clippy::not_unsafe_ptr_arg_deref)] |
116 | 250k | pub fn set_tx(&self, flow: *const Flow, tx_id: u64) { |
117 | 250k | unsafe { |
118 | 250k | SCAppLayerFrameSetTxIdById(flow, self.direction(), self.id, tx_id); |
119 | 250k | }; |
120 | 250k | } |
121 | | |
122 | | /// A variation of `set_tx` for use when running Rust unit tests as |
123 | | /// the C functions for building a frame are not available for |
124 | | /// linkage. |
125 | | #[cfg(test)] |
126 | | pub fn set_tx(&self, _flow: *const Flow, _tx_id: u64) {} |
127 | | |
128 | | #[allow(clippy::not_unsafe_ptr_arg_deref)] |
129 | 431 | pub fn add_event(&self, flow: *const Flow, event: u8) { |
130 | 431 | unsafe { |
131 | 431 | SCAppLayerFrameAddEventById(flow, self.direction(), self.id, event); |
132 | 431 | }; |
133 | 431 | } |
134 | | } |