iris_core/conntrack/conn/
conn_layers.rs1#![doc(hidden)]
2use super::conn_actions::TrackedActions;
4use super::conn_state::{LayerState, StateTransition};
5use crate::conntrack::Actions;
6use crate::protocols::stream::{
7 ConnParser, ParseResult, ParserRegistry, ParsingState, ProbeRegistryResult, SessionData,
8 SessionProto,
9};
10use crate::protocols::Session;
11use crate::L4Pdu;
12
13lazy_static! {
14 static ref DEFAULT_SESSION: Session = Session {
15 data: SessionData::Null,
16 id: 0,
17 };
18}
19
20#[derive(Debug)]
23pub enum Layer {
24 L7(L7Session),
26}
27pub const NUM_LAYERS: usize = 1;
28
29#[derive(PartialEq, Eq, Debug, Copy, Clone, Ord, PartialOrd, Hash)]
32#[repr(usize)]
33pub enum SupportedLayer {
34 L4,
35 L7,
36}
37
38pub(crate) trait TrackableLayer {
40 fn process_stream(&mut self, pdu: &mut L4Pdu, registry: &ParserRegistry) -> StateTransition;
46
47 fn needs_process(&self, tx: StateTransition, pdu: &L4Pdu) -> bool;
52
53 fn drop(&self) -> bool;
56
57 fn needs_stream(&self) -> bool;
60
61 fn end_state_tx(&mut self);
65
66 fn handle_terminate(&mut self) -> Option<StateTransition>;
69}
70
71impl Layer {
72 pub fn layer_info_mut(&mut self) -> &mut LayerInfo {
74 match self {
75 Layer::L7(session) => &mut session.linfo,
76 }
77 }
78
79 pub fn layer_info(&self) -> &LayerInfo {
80 match self {
81 Layer::L7(session) => &session.linfo,
82 }
83 }
84
85 pub fn extend_actions(&mut self, action: &TrackedActions) {
87 self.layer_info_mut().actions.extend(action)
88 }
89
90 pub fn last_session(&self) -> &Session {
92 match self {
93 Layer::L7(session) => match session.sessions.last() {
94 Some(s) => s,
95 None => &DEFAULT_SESSION,
96 },
97 }
98 }
99
100 pub fn drain_sessions(&mut self) -> Vec<Session> {
101 match self {
102 Layer::L7(session) => session.parser.drain_sessions(),
103 }
104 }
105
106 pub fn first_session(&self) -> &Session {
107 match self {
108 Layer::L7(session) => match session.sessions.first() {
109 Some(s) => s,
110 None => &DEFAULT_SESSION,
111 },
112 }
113 }
114
115 pub fn sessions(&self) -> &Vec<Session> {
116 match self {
117 Layer::L7(session) => &session.sessions,
118 }
119 }
120
121 pub fn last_protocol(&self) -> SessionProto {
122 match self {
123 Layer::L7(session) => session.get_protocol(),
124 }
125 }
126}
127
128impl TrackableLayer for Layer {
129 fn process_stream(&mut self, pdu: &mut L4Pdu, registry: &ParserRegistry) -> StateTransition {
130 match self {
131 Layer::L7(session) => session.process_stream(pdu, registry),
132 }
133 }
134
135 fn needs_process(&self, tx: StateTransition, pdu: &L4Pdu) -> bool {
136 match self {
137 Layer::L7(session) => session.needs_process(tx, pdu),
138 }
139 }
140
141 fn drop(&self) -> bool {
142 match self {
143 Layer::L7(session) => session.drop(),
144 }
145 }
146
147 fn needs_stream(&self) -> bool {
148 match self {
149 Layer::L7(session) => session.needs_stream(),
150 }
151 }
152
153 fn end_state_tx(&mut self) {
154 match self {
155 Layer::L7(session) => session.end_state_tx(),
156 }
157 }
158
159 fn handle_terminate(&mut self) -> Option<StateTransition> {
160 match self {
161 Layer::L7(session) => session.handle_terminate(),
162 }
163 }
164}
165
166#[derive(Debug, Clone, PartialEq, Eq)]
168pub struct LayerInfo {
169 pub state: LayerState,
170 pub actions: TrackedActions,
171}
172
173impl Default for LayerInfo {
174 fn default() -> Self {
175 Self::new()
176 }
177}
178
179impl LayerInfo {
180 pub fn new() -> Self {
181 Self {
182 state: LayerState::Discovery,
183 actions: TrackedActions::new(),
184 }
185 }
186
187 pub(crate) fn drop(&self) -> bool {
188 self.state == LayerState::None || self.actions.drop()
189 }
190}
191
192#[derive(Debug)]
194pub struct L7Session {
195 pub linfo: LayerInfo,
197 pub parser: ConnParser,
199 pub sessions: Vec<Session>,
201 pub pending_sessions: Vec<Session>,
203 }
205
206impl L7Session {
207 pub fn new() -> Self {
210 Self {
211 linfo: LayerInfo::new(),
212 parser: ConnParser::Unknown,
213 sessions: Vec::new(),
214 pending_sessions: Vec::new(),
215 }
216 }
217
218 pub fn get_protocol(&self) -> SessionProto {
220 match self.linfo.state {
221 LayerState::Discovery => SessionProto::Probing,
222 _ => self.parser.protocol(),
223 }
224 }
225}
226
227impl Default for L7Session {
229 fn default() -> Self {
230 Self::new()
231 }
232}
233
234impl TrackableLayer for L7Session {
235 fn end_state_tx(&mut self) {
236 #[cfg(debug_assertions)]
237 {
238 log::debug!(
239 "End state transition, state: {:?}, L7 actions: {:?}",
240 self.linfo.state,
241 self.linfo.actions.active
242 );
243 }
244 if self.linfo.actions.needs_parse()
246 && matches!(self.linfo.state, LayerState::Payload)
247 && !matches!(
248 self.parser.session_parsed_state(),
249 ParsingState::Parsing | ParsingState::Probing
250 )
251 {
252 self.linfo.actions.clear(&Actions::Parse);
253 }
254 }
255
256 fn needs_process(&self, tx: StateTransition, pdu: &L4Pdu) -> bool {
257 if self.linfo.state == LayerState::None {
258 return false;
259 }
260 (tx == StateTransition::L7OnDisc && pdu.length() > 0)
261 || (tx == StateTransition::L7EndHdrs && pdu.ctxt.app_offset.is_some())
262 }
263
264 fn drop(&self) -> bool {
265 self.linfo.drop()
266 }
267
268 fn needs_stream(&self) -> bool {
269 self.linfo.actions.needs_parse()
270 }
271
272 fn handle_terminate(&mut self) -> Option<StateTransition> {
277 let state = self.linfo.state;
278 self.linfo.state = LayerState::None;
279 if !self.linfo.actions.needs_parse() {
280 return None;
281 }
282 if matches!(state, LayerState::None) {
283 return None;
284 }
285 if matches!(state, LayerState::Discovery) {
287 return Some(StateTransition::L7OnDisc);
288 }
289 self.pending_sessions.extend(self.parser.drain_sessions());
290 if self.pending_sessions.is_empty() {
292 return Some(StateTransition::L7EndHdrs);
293 }
294 self.sessions.push(self.pending_sessions.pop().unwrap());
296 if !self.sessions.is_empty() {
297 self.linfo.state = state;
299 }
300 Some(StateTransition::L7EndHdrs)
301 }
302
303 fn process_stream(&mut self, pdu: &mut L4Pdu, registry: &ParserRegistry) -> StateTransition {
304 match self.linfo.state {
305 LayerState::Discovery => {
306 match registry.probe_all(pdu) {
307 ProbeRegistryResult::Some(conn_parser) => {
308 self.parser = conn_parser;
310 self.linfo.state = LayerState::Headers;
311 return StateTransition::L7OnDisc;
312 }
313 ProbeRegistryResult::None => {
314 self.linfo.state = LayerState::None;
316 self.linfo.actions.clear(&Actions::Parse);
317 return StateTransition::L7OnDisc;
318 }
319 ProbeRegistryResult::Unsure => { }
320 }
321 }
322 LayerState::Headers => {
323 match self.parser.parse(pdu) {
324 ParseResult::HeadersDone(id) => {
325 if let Some(session) = self.parser.remove_session(id) {
326 self.sessions.push(session);
327 }
328 if let Some(offset) = self.parser.body_offset() {
329 pdu.ctxt.app_offset = Some(offset);
330 }
331 self.linfo.state = LayerState::Payload;
332 return StateTransition::L7EndHdrs;
333 }
334 ParseResult::None => {
335 self.linfo.state = LayerState::None;
336 return StateTransition::L7EndHdrs;
337 }
338 ParseResult::Done(id) => {
339 if let Some(session) = self.parser.remove_session(id) {
340 self.sessions.push(session);
341 }
342 self.linfo.state = LayerState::None;
343 return StateTransition::L7EndHdrs;
344 }
345 _ => { }
346 }
347 }
348 LayerState::Payload => {
349 pdu.ctxt.app_offset = Some(0);
350 if self.linfo.actions.needs_parse() {
351 match self.parser.session_parsed_state() {
352 ParsingState::Probing => {
353 }
355 ParsingState::Parsing => {
356 }
358 _ => {}
359 }
360 }
361 }
364 LayerState::None => {
365 }
367 }
368 StateTransition::Packet
369 }
370}