falco_event/events/
payload.rs

1use crate::events::EventMetadata;
2use crate::fields::FromBytesError;
3use std::collections::BTreeSet;
4use std::io::Write;
5use thiserror::Error;
6
7/// Represents the direction of an event, either an entry or an exit.
8#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
9#[allow(missing_docs)]
10pub enum EventDirection {
11    Entry,
12    Exit,
13}
14
15/// A trait to identify event payloads in the plugin framework.
16///
17/// Each event has two main identifiers:
18/// - `ID`: a unique identifier for the event type, which is a 16-bit unsigned integer.
19/// - `SOURCE`: the name of the event source. For plugin events, this is the name of the plugin
20///   that generated the event. For syscall events, this is always `Some("syscall")`.
21///
22/// The source can be `None` if the event can come from multiple sources, such as in the case of
23/// async or plugin events coming from different plugins.
24#[allow(missing_docs)]
25pub trait EventPayload {
26    const ID: u16;
27    const SOURCE: Option<&'static str>;
28}
29
30/// Get the event direction from the event type ID.
31#[inline]
32pub const fn event_direction(event_type_id: u16) -> EventDirection {
33    match event_type_id % 2 {
34        0 => EventDirection::Entry,
35        1 => EventDirection::Exit,
36        _ => unreachable!(),
37    }
38}
39
40/// A trait to identify a group of event payloads, each having a unique identifier and source.
41pub trait AnyEventPayload {
42    /// The sources of the events that this payload type can represent.
43    const SOURCES: &'static [Option<&'static str>];
44
45    /// The event types that this payload type can represent.
46    const EVENT_TYPES: &'static [u16];
47
48    /// Get all the event sources for this payload type
49    ///
50    /// This is intended for internal use only. If all the items in `SOURCES` are `Some()`,
51    /// the function returns the inner strings with duplicates removed. If any item is `None`
52    /// (indicating a supported event may come from any source), an empty vector is returned
53    /// (again, indicating all sources).
54    fn event_sources() -> Vec<&'static str> {
55        let mut sources = BTreeSet::new();
56        for source in Self::SOURCES {
57            if let Some(source) = source {
58                sources.insert(*source);
59            } else {
60                return Vec::new();
61            }
62        }
63
64        sources.into_iter().collect()
65    }
66}
67
68impl<T: EventPayload> AnyEventPayload for T {
69    const SOURCES: &'static [Option<&'static str>] = const {
70        match T::SOURCE {
71            Some(s) => &[Some(s)],
72            None => &[],
73        }
74    };
75    const EVENT_TYPES: &'static [u16] = &[T::ID];
76}
77
78/// Error type for parsing event payloads from bytes
79#[derive(Debug, Error)]
80pub enum PayloadFromBytesError {
81    /// Failed to parse a particular field
82    #[error("failed to parse field {0}")]
83    NamedField(&'static str, #[source] FromBytesError),
84
85    /// Type mismatch
86    #[error("type mismatch")]
87    TypeMismatch,
88
89    /// Truncated event
90    #[error("truncated event (wanted {wanted}, got {got})")]
91    TruncatedEvent {
92        /// expected length
93        wanted: usize,
94        /// actual length
95        got: usize,
96    },
97
98    /// Unsupported event type
99    #[error("unsupported event type {0}")]
100    UnsupportedEventType(u16),
101}
102
103/// Trait for converting event payloads to bytes
104pub trait PayloadToBytes {
105    /// Get the binary size of the payload
106    ///
107    /// This is the size of the payload in bytes, excluding the event header. This can (and should)
108    /// be used to preallocate buffers for writing the payload.
109    fn binary_size(&self) -> usize;
110
111    /// Write the payload to a writer implementing `[std::io::Write]`.
112    fn write<W: Write>(&self, metadata: &EventMetadata, writer: W) -> std::io::Result<()>;
113}