falco_plugin/plugin/extract/
wrappers.rs1use crate::plugin::base::PluginWrapper;
2use crate::plugin::error::ffi_result::FfiResult;
3use crate::plugin::event::EventInput;
4use crate::plugin::extract::ExtractPlugin;
5use crate::tables::LazyTableReader;
6use falco_plugin_api::plugin_api__bindgen_ty_2 as extract_plugin_api;
7use falco_plugin_api::ss_plugin_rc;
8use falco_plugin_api::{ss_plugin_event_input, ss_plugin_rc_SS_PLUGIN_FAILURE};
9use falco_plugin_api::{ss_plugin_field_extract_input, ss_plugin_t};
10use std::any::TypeId;
11use std::collections::BTreeMap;
12use std::ffi::{c_char, CString};
13use std::sync::Mutex;
14
15#[diagnostic::on_unimplemented(
23 message = "Extract plugin is not exported",
24 note = "use either `extract_plugin!` or `static_plugin!`"
25)]
26pub unsafe trait ExtractPluginExported {}
27
28pub trait ExtractPluginFallbackApi {
29 const EXTRACT_API: extract_plugin_api = extract_plugin_api {
30 get_extract_event_types: None,
31 get_extract_event_sources: None,
32 get_fields: None,
33 extract_fields: None,
34 };
35
36 const IMPLEMENTS_EXTRACT: bool = false;
37}
38impl<T> ExtractPluginFallbackApi for T {}
39
40#[allow(missing_debug_implementations)]
41pub struct ExtractPluginApi<T>(std::marker::PhantomData<T>);
42
43impl<T: ExtractPlugin> ExtractPluginApi<T> {
44 pub const EXTRACT_API: extract_plugin_api = extract_plugin_api {
45 get_extract_event_types: Some(plugin_get_extract_event_types::<T>),
46 get_extract_event_sources: Some(plugin_get_extract_event_sources::<T>),
47 get_fields: Some(plugin_get_fields::<T>),
48 extract_fields: Some(plugin_extract_fields::<T>),
49 };
50
51 pub const IMPLEMENTS_EXTRACT: bool = true;
52}
53
54pub extern "C-unwind" fn plugin_get_fields<T: ExtractPlugin>() -> *const c_char {
55 T::get_fields().as_ptr()
56}
57
58pub unsafe extern "C-unwind" fn plugin_get_extract_event_types<T: ExtractPlugin>(
62 numtypes: *mut u32,
63 _plugin: *mut ss_plugin_t,
64) -> *mut u16 {
65 let types = T::EVENT_TYPES;
66 unsafe { *numtypes = types.len() as u32 };
67 types.as_ptr() as *const u16 as *mut u16 }
69
70pub extern "C-unwind" fn plugin_get_extract_event_sources<T: ExtractPlugin>() -> *const c_char {
72 static SOURCES: Mutex<BTreeMap<TypeId, CString>> = Mutex::new(BTreeMap::new());
73 let ty = TypeId::of::<T>();
74 let mut sources_map = SOURCES.lock().unwrap();
75 sources_map
78 .entry(ty)
79 .or_insert_with(|| {
80 let sources = serde_json::to_string(T::EVENT_SOURCES)
81 .expect("failed to serialize event source array");
82 CString::new(sources.into_bytes()).expect("failed to add NUL to event source array")
83 })
84 .as_ptr()
85}
86
87pub unsafe extern "C-unwind" fn plugin_extract_fields<T: ExtractPlugin>(
91 plugin: *mut ss_plugin_t,
92 event_input: *const ss_plugin_event_input,
93 extract_input: *const ss_plugin_field_extract_input,
94) -> ss_plugin_rc {
95 let plugin = plugin as *mut PluginWrapper<T>;
96 unsafe {
97 let Some(plugin) = plugin.as_mut() else {
98 return ss_plugin_rc_SS_PLUGIN_FAILURE;
99 };
100 let Some(actual_plugin) = &mut plugin.plugin else {
101 return ss_plugin_rc_SS_PLUGIN_FAILURE;
102 };
103
104 let Some(event_input) = event_input.as_ref() else {
105 return ss_plugin_rc_SS_PLUGIN_FAILURE;
106 };
107 let event_input = EventInput(*event_input);
108
109 let Some(extract_input) = extract_input.as_ref() else {
110 return ss_plugin_rc_SS_PLUGIN_FAILURE;
111 };
112
113 let fields =
114 std::slice::from_raw_parts_mut(extract_input.fields, extract_input.num_fields as usize);
115
116 let Some(reader_ext) = extract_input.table_reader_ext.as_ref() else {
117 return ss_plugin_rc_SS_PLUGIN_FAILURE;
118 };
119
120 let offsets = extract_input.value_offsets.as_mut();
121
122 let table_reader = LazyTableReader::new(reader_ext, actual_plugin.last_error.clone());
123
124 plugin.field_storage.reset();
125 actual_plugin
126 .plugin
127 .extract_fields(
128 &event_input,
129 &table_reader,
130 fields,
131 offsets,
132 &plugin.field_storage,
133 )
134 .rc(&mut plugin.error_buf)
135 }
136}
137
138#[macro_export]
143macro_rules! extract_plugin {
144 ($ty:ty) => {
145 unsafe impl $crate::internals::extract::wrappers::ExtractPluginExported for $ty {}
146
147 $crate::wrap_ffi! {
148 #[unsafe(no_mangle)]
149 use $crate::internals::extract::wrappers: <$ty>;
150
151 unsafe fn plugin_get_extract_event_sources() -> *const ::std::ffi::c_char;
152 unsafe fn plugin_get_extract_event_types(
153 numtypes: *mut u32,
154 plugin: *mut falco_plugin::api::ss_plugin_t,
155 ) -> *mut u16;
156 unsafe fn plugin_get_fields() -> *const ::std::ffi::c_char;
157 unsafe fn plugin_extract_fields(
158 plugin: *mut falco_plugin::api::ss_plugin_t,
159 event_input: *const falco_plugin::api::ss_plugin_event_input,
160 extract_input: *const falco_plugin::api::ss_plugin_field_extract_input,
161 ) -> i32;
162 }
163
164 #[allow(dead_code)]
165 fn __typecheck_plugin_extract_api() -> falco_plugin::api::plugin_api__bindgen_ty_2 {
166 falco_plugin::api::plugin_api__bindgen_ty_2 {
167 get_extract_event_sources: Some(plugin_get_extract_event_sources),
168 get_extract_event_types: Some(plugin_get_extract_event_types),
169 get_fields: Some(plugin_get_fields),
170 extract_fields: Some(plugin_extract_fields),
171 }
172 }
173 };
174}