1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/* Copyright (C) 2017-2021 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
//! Module for bindings to the Suricata C frame API.
use crate::applayer::StreamSlice;
use crate::core::Flow;
#[cfg(not(test))]
use crate::core::STREAM_TOSERVER;
use crate::core::Direction;
#[cfg(not(test))]
#[repr(C)]
struct CFrame {
_private: [u8; 0],
}
// Defined in app-layer-register.h
extern {
#[cfg(not(test))]
fn AppLayerFrameNewByRelativeOffset(
flow: *const Flow, stream_slice: *const StreamSlice, frame_start_rel: u32, len: i64,
dir: i32, frame_type: u8,
) -> *const CFrame;
fn AppLayerFrameAddEventById(flow: *const Flow, dir: i32, id: i64, event: u8);
fn AppLayerFrameSetLengthById(flow: *const Flow, dir: i32, id: i64, len: i64);
fn AppLayerFrameSetTxIdById(flow: *const Flow, dir: i32, id: i64, tx_id: u64);
#[cfg(not(test))]
fn AppLayerFrameGetId(frame: *const CFrame) -> i64;
}
pub struct Frame {
pub id: i64,
direction: Direction,
}
impl std::fmt::Debug for Frame {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "frame: {}, direction: {}", self.id, self.direction)
}
}
impl Frame {
#[cfg(not(test))]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn new(
flow: *const Flow, stream_slice: &StreamSlice, frame_start: &[u8], frame_len: i64,
frame_type: u8,
) -> Option<Self> {
let offset = frame_start.as_ptr() as usize - stream_slice.as_slice().as_ptr() as usize;
SCLogDebug!("offset {} stream_slice.len() {} frame_start.len() {}", offset, stream_slice.len(), frame_start.len());
let frame = unsafe {
AppLayerFrameNewByRelativeOffset(
flow,
stream_slice,
offset as u32,
frame_len,
(stream_slice.flags() & STREAM_TOSERVER == 0).into(),
frame_type,
)
};
let id = unsafe { AppLayerFrameGetId(frame) };
if id > 0 {
Some(Self {
id,
direction: Direction::from(stream_slice.flags()),
})
} else {
None
}
}
/// A variation of `new` for use when running Rust unit tests as
/// the C functions for building a frame are not available for
/// linkage.
#[cfg(test)]
pub fn new(
_flow: *const Flow, _stream_slice: &StreamSlice, _frame_start: &[u8], _frame_len: i64,
_frame_type: u8,
) -> Option<Self> {
None
}
/// Conversion function to get the direction in the correct form for the
/// C frame methods which takes direction as a u32 value of 0 or 1 rather
/// than the flag value used internally by Frame.
fn direction(&self) -> i32 {
match self.direction {
Direction::ToServer => 0,
Direction::ToClient => 1,
}
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn set_len(&self, flow: *const Flow, len: i64) {
unsafe {
AppLayerFrameSetLengthById(flow, self.direction(), self.id, len);
};
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn set_tx(&self, flow: *const Flow, tx_id: u64) {
unsafe {
AppLayerFrameSetTxIdById(flow, self.direction(), self.id, tx_id);
};
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn add_event(&self, flow: *const Flow, event: u8) {
unsafe {
AppLayerFrameAddEventById(flow, self.direction(), self.id, event);
};
}
}
|