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}