falco_plugin/plugin/parse/mod.rs
1use crate::parse::EventInput;
2use crate::plugin::base::Plugin;
3use crate::plugin::error::last_error::LastError;
4use crate::plugin::parse::wrappers::ParsePluginExported;
5use crate::plugin::tables::vtable::writer::LazyTableWriter;
6use crate::tables::LazyTableReader;
7use falco_event::events::types::EventType;
8use falco_plugin_api::ss_plugin_event_parse_input;
9
10#[doc(hidden)]
11pub mod wrappers;
12
13/// # Support for event parse plugins
14pub trait ParsePlugin: Plugin + ParsePluginExported {
15 // TODO: document event_type vs anyevent vs individual event types somewhere prominent
16
17 /// # Supported event types
18 ///
19 /// This list contains the event types that this plugin will receive
20 /// for event parsing. Events that are not included in this list
21 /// will not be received by the plugin.
22 ///
23 /// This is a non-functional filter that should not influence the plugin's
24 /// functional behavior. Instead, this is a performance optimization
25 /// with the goal of avoiding unnecessary communication between the
26 /// framework and the plugin for events that are known to be not used for
27 /// event parsing.
28 ///
29 /// If this list is empty, then:
30 /// - the plugin will receive every event type if [`ParsePlugin::EVENT_SOURCES`]
31 /// is compatible with the "syscall" event source, otherwise
32 /// - the plugin will only receive events of plugin type [`source::PluginEvent`](`crate::source::PluginEvent`)
33 ///
34 /// **Note**: some notable event types are:
35 /// - [`EventType::ASYNCEVENT_E`], generated from async plugins
36 /// - [`EventType::PLUGINEVENT_E`], generated from source plugins
37 const EVENT_TYPES: &'static [EventType];
38
39 /// # Supported event sources
40 ///
41 /// This list contains the event sources that this plugin is capable of parsing.
42 ///
43 /// If this list is empty, then if plugin has sourcing capability, and implements a specific
44 /// event source, it will only receive events matching its event source, otherwise it will
45 /// receive events from all event sources.
46 ///
47 /// **Note**: one notable event source is called `syscall`
48 const EVENT_SOURCES: &'static [&'static str];
49
50 /// # Parse an event
51 ///
52 /// Receives an event from the current capture and parses its content.
53 /// The plugin is guaranteed to receive an event at most once, after any
54 /// operation related the event sourcing capability, and before
55 /// any operation related to the field extraction capability.
56 fn parse_event(&mut self, event: &EventInput, parse_input: &ParseInput) -> anyhow::Result<()>;
57}
58
59/// # The input to a parse plugin
60///
61/// It has two fields containing the vtables needed to access tables imported through
62/// the [tables API](`crate::tables`).
63///
64/// You will pass these vtables to all methods that read or write data from tables,
65/// but you won't interact with them otherwise. They're effectively tokens proving
66/// you're in the right context to read/write tables.
67#[derive(Debug)]
68pub struct ParseInput<'t> {
69 /// Accessors to read table entries
70 pub reader: LazyTableReader<'t>,
71 /// Accessors to modify table entries
72 pub writer: LazyTableWriter<'t>,
73}
74
75impl ParseInput<'_> {
76 pub(in crate::plugin::parse) unsafe fn try_from(
77 value: *const ss_plugin_event_parse_input,
78 last_error: LastError,
79 ) -> Result<Self, anyhow::Error> {
80 let input = unsafe {
81 value
82 .as_ref()
83 .ok_or_else(|| anyhow::anyhow!("Got null event parse input"))?
84 };
85
86 let reader = unsafe {
87 input
88 .table_reader_ext
89 .as_ref()
90 .ok_or_else(|| anyhow::anyhow!("Got null reader vtable"))?
91 };
92 let writer = unsafe {
93 input
94 .table_writer_ext
95 .as_ref()
96 .ok_or_else(|| anyhow::anyhow!("Got null writer vtable"))?
97 };
98
99 let reader = LazyTableReader::new(reader, last_error.clone());
100 let writer = LazyTableWriter::try_from(writer, last_error)?;
101
102 Ok(Self { reader, writer })
103 }
104}