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