1515 * 02110-1301, USA.
1616 */
1717
18+ use std:: marker:: PhantomData ;
1819use std:: os:: raw:: c_void;
20+ use std:: ptr:: NonNull ;
1921
20- use suricata_sys:: sys:: { Flow , Packet , ThreadVars } ;
22+ use suricata_sys:: sys:: { Flow as CFlow , Packet , ThreadVars } ;
2123use suricata_sys:: sys:: {
2224 SCFlowRegisterFinishCallback , SCFlowRegisterInitCallback , SCFlowRegisterUpdateCallback ,
2325} ;
2426
27+ /// Access to a Suricata flow for the lifetime of a callback.
28+ ///
29+ /// This type is intended to be the place where safe Rust accessors for C
30+ /// `Flow` fields are added. It deliberately does not implement `Deref` or
31+ /// `DerefMut` to the bindgen type, so field access can be exposed as reviewed
32+ /// methods instead of exposing the whole raw C layout as safe Rust API.
33+ pub struct Flow < ' a > {
34+ ptr : NonNull < CFlow > ,
35+ _marker : PhantomData < & ' a mut CFlow > ,
36+ }
37+
38+ impl < ' a > Flow < ' a > {
39+ /// Create a flow wrapper from a raw pointer.
40+ ///
41+ /// # Safety
42+ ///
43+ /// `ptr` must point to a live `Flow` that the caller may access for the
44+ /// duration of `'a`. The returned wrapper must not be stored beyond that
45+ /// validity period.
46+ pub unsafe fn from_ptr ( ptr : * mut CFlow ) -> Option < Self > {
47+ NonNull :: new ( ptr) . map ( |ptr| Self {
48+ ptr,
49+ _marker : PhantomData ,
50+ } )
51+ }
52+
53+ /// Return the wrapped raw C pointer.
54+ pub fn as_ptr ( & self ) -> * const CFlow {
55+ self . ptr . as_ptr ( )
56+ }
57+
58+ /// Return the wrapped raw C pointer as mutable.
59+ pub fn as_mut_ptr ( & mut self ) -> * mut CFlow {
60+ self . ptr . as_ptr ( )
61+ }
62+ }
63+
2564/// Register a flow initialization callback.
2665///
2766/// The callback is invoked whenever Suricata initializes a flow. It receives:
2867/// - `tv`: the `ThreadVars` for the thread creating the flow
29- /// - `f`: the newly initialized `Flow`
68+ /// - `flow`: access to the newly initialized `Flow`
3069/// - `p`: the packet related to creating the flow
3170///
32- /// # Safety
33- ///
34- /// The callback receives raw pointers from Suricata. These pointers are only
35- /// valid for the duration of the callback invocation and must not be stored.
36- ///
37- /// The callback must not panic.
71+ /// The flow wrapper is only valid for the duration of the callback invocation
72+ /// and must not be stored. The callback must not panic.
3873pub fn register_init_callback < F > ( callback : F ) -> Result < ( ) , & ' static str >
3974where
40- F : Fn ( * mut ThreadVars , * mut Flow , * const Packet ) + Send + Sync + ' static ,
75+ F : for < ' a > Fn ( * mut ThreadVars , Flow < ' a > , * const Packet ) + Send + Sync + ' static ,
4176{
4277 let user = Box :: into_raw ( Box :: new ( callback) ) as * mut c_void ;
4378 if unsafe { SCFlowRegisterInitCallback ( Some ( init_callback_wrapper :: < F > ) , user) } {
@@ -55,18 +90,14 @@ where
5590/// The callback is invoked whenever Suricata updates a flow with a packet. It
5691/// receives:
5792/// - `tv`: the `ThreadVars` for the thread updating the flow
58- /// - `f`: the flow being updated
93+ /// - `flow`: access to the flow being updated
5994/// - `p`: the packet responsible for the flow update
6095///
61- /// # Safety
62- ///
63- /// The callback receives raw pointers from Suricata. These pointers are only
64- /// valid for the duration of the callback invocation and must not be stored.
65- ///
66- /// The callback must not panic.
96+ /// The flow wrapper is only valid for the duration of the callback invocation
97+ /// and must not be stored. The callback must not panic.
6798pub fn register_update_callback < F > ( callback : F ) -> Result < ( ) , & ' static str >
6899where
69- F : Fn ( * mut ThreadVars , * mut Flow , * mut Packet ) + Send + Sync + ' static ,
100+ F : for < ' a > Fn ( * mut ThreadVars , Flow < ' a > , * mut Packet ) + Send + Sync + ' static ,
70101{
71102 let user = Box :: into_raw ( Box :: new ( callback) ) as * mut c_void ;
72103 if unsafe { SCFlowRegisterUpdateCallback ( Some ( update_callback_wrapper :: < F > ) , user) } {
@@ -83,17 +114,13 @@ where
83114///
84115/// The callback is invoked when Suricata is finished with a flow. It receives:
85116/// - `tv`: the `ThreadVars` for the thread finishing the flow
86- /// - `f`: the flow being finished
87- ///
88- /// # Safety
89- ///
90- /// The callback receives raw pointers from Suricata. These pointers are only
91- /// valid for the duration of the callback invocation and must not be stored.
117+ /// - `flow`: access to the flow being finished
92118///
93- /// The callback must not panic.
119+ /// The flow wrapper is only valid for the duration of the callback invocation
120+ /// and must not be stored. The callback must not panic.
94121pub fn register_finish_callback < F > ( callback : F ) -> Result < ( ) , & ' static str >
95122where
96- F : Fn ( * mut ThreadVars , * mut Flow ) + Send + Sync + ' static ,
123+ F : for < ' a > Fn ( * mut ThreadVars , Flow < ' a > ) + Send + Sync + ' static ,
97124{
98125 let user = Box :: into_raw ( Box :: new ( callback) ) as * mut c_void ;
99126 if unsafe { SCFlowRegisterFinishCallback ( Some ( finish_callback_wrapper :: < F > ) , user) } {
@@ -107,28 +134,37 @@ where
107134}
108135
109136unsafe extern "C" fn init_callback_wrapper < F > (
110- tv : * mut ThreadVars , f : * mut Flow , p : * const Packet , user : * mut c_void ,
137+ tv : * mut ThreadVars , f : * mut CFlow , p : * const Packet , user : * mut c_void ,
111138) where
112- F : Fn ( * mut ThreadVars , * mut Flow , * const Packet ) + Send + Sync + ' static ,
139+ F : for < ' a > Fn ( * mut ThreadVars , Flow < ' a > , * const Packet ) + Send + Sync + ' static ,
113140{
114- let callback = & * ( user as * const F ) ;
115- callback ( tv, f, p) ;
141+ let Some ( flow) = ( unsafe { Flow :: from_ptr ( f) } ) else {
142+ return ;
143+ } ;
144+ let callback = unsafe { & * ( user as * const F ) } ;
145+ callback ( tv, flow, p) ;
116146}
117147
118148unsafe extern "C" fn update_callback_wrapper < F > (
119- tv : * mut ThreadVars , f : * mut Flow , p : * mut Packet , user : * mut c_void ,
149+ tv : * mut ThreadVars , f : * mut CFlow , p : * mut Packet , user : * mut c_void ,
120150) where
121- F : Fn ( * mut ThreadVars , * mut Flow , * mut Packet ) + Send + Sync + ' static ,
151+ F : for < ' a > Fn ( * mut ThreadVars , Flow < ' a > , * mut Packet ) + Send + Sync + ' static ,
122152{
123- let callback = & * ( user as * const F ) ;
124- callback ( tv, f, p) ;
153+ let Some ( flow) = ( unsafe { Flow :: from_ptr ( f) } ) else {
154+ return ;
155+ } ;
156+ let callback = unsafe { & * ( user as * const F ) } ;
157+ callback ( tv, flow, p) ;
125158}
126159
127160unsafe extern "C" fn finish_callback_wrapper < F > (
128- tv : * mut ThreadVars , f : * mut Flow , user : * mut c_void ,
161+ tv : * mut ThreadVars , f : * mut CFlow , user : * mut c_void ,
129162) where
130- F : Fn ( * mut ThreadVars , * mut Flow ) + Send + Sync + ' static ,
163+ F : for < ' a > Fn ( * mut ThreadVars , Flow < ' a > ) + Send + Sync + ' static ,
131164{
132- let callback = & * ( user as * const F ) ;
133- callback ( tv, f) ;
165+ let Some ( flow) = ( unsafe { Flow :: from_ptr ( f) } ) else {
166+ return ;
167+ } ;
168+ let callback = unsafe { & * ( user as * const F ) } ;
169+ callback ( tv, flow) ;
134170}
0 commit comments