Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}