Skip to main content

retina_core/subscription/
mod.rs

1//! Subscribable data types.
2//!
3//! A subscription is a request for a callback on a subset of network traffic specified by a filter.
4//! Callback functions are implemented as a closure that takes a subscribable data type as the
5//! parameter and immutably borrows values from the environment. Built-in subscribable types can
6//! be customized within the framework to provide additional data to the callback if needed.
7
8pub mod connection;
9pub mod connection_frame;
10pub mod dns_transaction;
11pub mod frame;
12pub mod http_transaction;
13pub mod quic_stream;
14pub mod tls_handshake;
15pub mod zc_frame;
16
17// Re-export subscribable types for more convenient usage.
18pub use self::connection::Connection;
19pub use self::connection_frame::ConnectionFrame;
20pub use self::dns_transaction::DnsTransaction;
21pub use self::frame::Frame;
22pub use self::http_transaction::HttpTransaction;
23pub use self::quic_stream::QuicStream;
24pub use self::tls_handshake::TlsHandshake;
25pub use self::zc_frame::ZcFrame;
26
27use crate::conntrack::conn_id::FiveTuple;
28use crate::conntrack::pdu::L4Pdu;
29use crate::conntrack::ConnTracker;
30use crate::filter::{ConnFilterFn, PacketFilterFn, SessionFilterFn};
31use crate::filter::{FilterFactory, FilterResult};
32use crate::memory::mbuf::Mbuf;
33use crate::protocols::stream::{ConnData, ConnParser, Session};
34
35#[cfg(feature = "timing")]
36use crate::timing::timer::Timers;
37
38/// The abstraction level of the subscribable type.
39#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
40pub enum Level {
41    /// Suitable for analyzing individual packets or frames where connection-level semantics are
42    /// unnecessary.
43    Packet,
44    /// Suitable for analyzing entire connections, whether as a single record or a stream.
45    Connection,
46    /// Suitable for analyzing session-level data, of which there may be multiple instances per
47    /// connection.
48    Session,
49}
50
51/// Represents a generic subscribable type. All subscribable types must implement this trait.
52pub trait Subscribable {
53    type Tracked: Trackable<Subscribed = Self>;
54
55    /// Returns the subscription level.
56    fn level() -> Level;
57
58    /// Returns a list of protocol parsers required to parse the subscribable type.
59    fn parsers() -> Vec<ConnParser>;
60
61    /// Process a single incoming packet.
62    fn process_packet(
63        mbuf: Mbuf,
64        subscription: &Subscription<Self>,
65        conn_tracker: &mut ConnTracker<Self::Tracked>,
66    ) where
67        Self: Sized;
68}
69
70/// Tracks subscribable types throughout the duration of a connection.
71pub trait Trackable {
72    type Subscribed: Subscribable<Tracked = Self>;
73
74    /// Create a new Trackable type to manage subscription data for the duration of the connection
75    /// represented by `five_tuple`.
76    fn new(five_tuple: FiveTuple) -> Self;
77
78    /// Update tracked subscription data prior to a full filter match.
79    fn pre_match(&mut self, pdu: L4Pdu, session_id: Option<usize>);
80
81    /// Update tracked subscription data on a full filter match.
82    fn on_match(&mut self, session: Session, subscription: &Subscription<Self::Subscribed>);
83
84    /// Update tracked subscription data after a full filter match.
85    fn post_match(&mut self, pdu: L4Pdu, subscription: &Subscription<Self::Subscribed>);
86
87    /// Update tracked subscription data on connection termination.
88    fn on_terminate(&mut self, subscription: &Subscription<Self::Subscribed>);
89}
90
91/// A request for a callback on a subset of traffic specified by the filter.
92#[doc(hidden)]
93pub struct Subscription<'a, S>
94where
95    S: Subscribable,
96{
97    packet_filter: PacketFilterFn,
98    conn_filter: ConnFilterFn,
99    session_filter: SessionFilterFn,
100    callback: Box<dyn Fn(S) + 'a>,
101    #[cfg(feature = "timing")]
102    pub(crate) timers: Timers,
103}
104
105impl<'a, S> Subscription<'a, S>
106where
107    S: Subscribable,
108{
109    /// Creates a new subscription from a filter and a callback.
110    pub(crate) fn new(factory: FilterFactory, cb: impl Fn(S) + 'a) -> Self {
111        Subscription {
112            packet_filter: factory.packet_filter,
113            conn_filter: factory.conn_filter,
114            session_filter: factory.session_filter,
115            callback: Box::new(cb),
116            #[cfg(feature = "timing")]
117            timers: Timers::new(),
118        }
119    }
120
121    /// Invokes the software packet filter.
122    pub(crate) fn filter_packet(&self, mbuf: &Mbuf) -> FilterResult {
123        (self.packet_filter)(mbuf)
124    }
125
126    /// Invokes the connection filter.
127    pub(crate) fn filter_conn(&self, conn: &ConnData) -> FilterResult {
128        (self.conn_filter)(conn)
129    }
130
131    /// Invokes the application-layer session filter. The `idx` parameter is the numerical ID of the
132    /// session.
133    pub(crate) fn filter_session(&self, session: &Session, idx: usize) -> bool {
134        (self.session_filter)(session, idx)
135    }
136
137    /// Invoke the callback on `S`.
138    pub(crate) fn invoke(&self, obj: S) {
139        tsc_start!(t0);
140        (self.callback)(obj);
141        tsc_record!(self.timers, "callback", t0);
142    }
143}