11use std:: ptr:: null_mut;
22
33use suricata_ffi:: eve:: { self , SCJsonBuilder } ;
4- use suricata_ffi:: flow:: { self , Flow } ;
4+ use suricata_ffi:: flow:: { self , Flow , FlowStorage } ;
55use suricata_ffi:: jsonbuilder:: JsonBuilder ;
66use suricata_ffi:: thread:: { self , ThreadStorage , ThreadVars } ;
77use suricata_ffi:: { SCLogError , SCLogNotice , SCLogWarning } ;
@@ -13,6 +13,12 @@ struct ThreadState {
1313 flows : u64 ,
1414}
1515
16+ /// Per-flow state stored in Suricata flow storage.
17+ #[ derive( Default ) ]
18+ struct FlowState {
19+ packets : u64 ,
20+ }
21+
1622unsafe extern "C" fn init ( ) {
1723 suricata_ffi:: plugin:: init ( ) ;
1824 SCLogNotice ! ( "Initializing rust example plugin" ) ;
@@ -26,29 +32,41 @@ unsafe extern "C" fn init() {
2632 return ;
2733 }
2834 } ;
35+ let flow_storage = match FlowStorage :: < FlowState > :: register ( "rust-example-flow" ) {
36+ Ok ( storage) => storage,
37+ Err ( err) => {
38+ SCLogError ! ( "Failed to register rust example flow storage: {}" , err) ;
39+ return ;
40+ }
41+ } ;
2942
30- if let Err ( err) = register_eve_callbacks ( ) {
43+ if let Err ( err) = register_eve_callbacks ( flow_storage ) {
3144 SCLogError ! ( "Failed to register rust example EVE callbacks: {}" , err) ;
3245 }
33- if let Err ( err) = register_flow_callbacks ( thread_storage) {
46+ if let Err ( err) = register_flow_callbacks ( thread_storage, flow_storage ) {
3447 SCLogError ! ( "Failed to register rust example flow callbacks: {}" , err) ;
3548 }
3649 if let Err ( err) = register_thread_callbacks ( thread_storage) {
3750 SCLogError ! ( "Failed to register rust example thread callbacks: {}" , err) ;
3851 }
3952}
4053
41- fn register_eve_callbacks ( ) -> Result < ( ) , & ' static str > {
54+ fn register_eve_callbacks ( flow_storage : FlowStorage < FlowState > ) -> Result < ( ) , & ' static str > {
4255 if !unsafe { SCEveRegisterCallback ( Some ( log_eve_raw) , null_mut ( ) ) } {
4356 return Err ( "Failed to register raw EVE callback" ) ;
4457 }
45- eve:: register_callback ( log_eve_wrapped)
58+ eve:: register_callback ( move |tv , p , f , jb| log_eve_wrapped ( flow_storage , tv , p , f , jb ) )
4659}
4760
48- fn register_flow_callbacks ( storage : ThreadStorage < ThreadState > ) -> Result < ( ) , & ' static str > {
49- flow:: register_init_callback ( move |tv, f, p| log_flow_init ( storage, tv, f, p) ) ?;
50- flow:: register_update_callback ( log_flow_update) ?;
51- flow:: register_finish_callback ( log_flow_finish) ?;
61+ fn register_flow_callbacks (
62+ thread_storage : ThreadStorage < ThreadState > ,
63+ flow_storage : FlowStorage < FlowState > ,
64+ ) -> Result < ( ) , & ' static str > {
65+ flow:: register_init_callback ( move |tv, f, p| {
66+ log_flow_init ( thread_storage, flow_storage, tv, f, p)
67+ } ) ?;
68+ flow:: register_update_callback ( move |tv, f, p| log_flow_update ( flow_storage, tv, f, p) ) ?;
69+ flow:: register_finish_callback ( move |tv, f| log_flow_finish ( flow_storage, tv, f) ) ?;
5270 Ok ( ( ) )
5371}
5472
@@ -70,6 +88,7 @@ unsafe extern "C" fn log_eve_raw(
7088}
7189
7290fn log_eve_wrapped (
91+ flow_storage : FlowStorage < FlowState > ,
7392 _tv : & mut ThreadVars ,
7493 _p : * const Packet ,
7594 f : Option < & mut Flow > ,
@@ -78,6 +97,13 @@ fn log_eve_wrapped(
7897 jb. open_object ( "rust_wrapped" ) ?;
7998 jb. set_string ( "example" , "eve-callback" ) ?;
8099 jb. set_string ( "has_flow" , if f. is_some ( ) { "true" } else { "false" } ) ?;
100+
101+ // If we have a flow, log something from flow storage.
102+ if let Some ( f) = f {
103+ if let Some ( state) = flow_storage. get ( f) {
104+ jb. set_uint ( "flow_packets" , state. packets ) ?;
105+ }
106+ }
81107 jb. close ( ) ?;
82108 Ok ( ( ) )
83109}
@@ -94,13 +120,14 @@ fn on_thread_init(storage: ThreadStorage<ThreadState>, tv: &mut ThreadVars) {
94120}
95121
96122fn log_flow_init (
97- storage : ThreadStorage < ThreadState > ,
123+ thread_storage : ThreadStorage < ThreadState > ,
124+ flow_storage : FlowStorage < FlowState > ,
98125 tv : & mut ThreadVars ,
99126 f : & mut Flow ,
100127 _p : * const Packet ,
101128) {
102129 // Count flows seen by this thread using the per-thread storage.
103- let flows = match storage . get_mut ( tv) {
130+ let flows = match thread_storage . get_mut ( tv) {
104131 Some ( state) => {
105132 state. flows += 1 ;
106133 state. flows
@@ -110,23 +137,48 @@ fn log_flow_init(
110137 0
111138 }
112139 } ;
140+ // Initialize the per-flow storage for this flow.
141+ if let Err ( err) = flow_storage. get_or_insert_with ( f, FlowState :: default) {
142+ SCLogError ! ( "failed to initialize rust example flow storage: {}" , err) ;
143+ }
113144 SCLogNotice ! (
114145 "rust example flow init callback: flow={:p}, thread_flows={}" ,
115146 f. as_ptr( ) ,
116147 flows
117148 ) ;
118149}
119150
120- fn log_flow_update ( _tv : & mut ThreadVars , f : & mut Flow , _p : * mut Packet ) {
151+ fn log_flow_update (
152+ flow_storage : FlowStorage < FlowState > ,
153+ _tv : & mut ThreadVars ,
154+ f : & mut Flow ,
155+ _p : * mut Packet ,
156+ ) {
157+ // Count packets seen on this flow using the per-flow storage.
158+ let packets = match flow_storage. get_mut ( f) {
159+ Some ( state) => {
160+ state. packets += 1 ;
161+ state. packets
162+ }
163+ None => {
164+ SCLogWarning ! ( "rust example flow storage was not initialized" ) ;
165+ 0
166+ }
167+ } ;
121168 SCLogNotice ! (
122- "rust example flow update callback: flow={:p}, packet={:p }" ,
169+ "rust example flow update callback: flow={:p}, flow_packets={ }" ,
123170 f. as_ptr( ) ,
124- _p
171+ packets
125172 ) ;
126173}
127174
128- fn log_flow_finish ( _tv : & mut ThreadVars , f : & mut Flow ) {
129- SCLogNotice ! ( "rust example flow finish callback: flow={:p}" , f. as_ptr( ) ) ;
175+ fn log_flow_finish ( flow_storage : FlowStorage < FlowState > , _tv : & mut ThreadVars , f : & mut Flow ) {
176+ let packets = flow_storage. get ( f) . map ( |state| state. packets ) . unwrap_or ( 0 ) ;
177+ SCLogNotice ! (
178+ "rust example flow finish callback: flow={:p}, flow_packets={}" ,
179+ f. as_ptr( ) ,
180+ packets
181+ ) ;
130182}
131183
132184#[ no_mangle]
0 commit comments