iris_core/conntrack/conn/
mod.rs1pub mod conn_actions;
10pub mod conn_info;
11pub mod conn_layers;
12pub mod conn_state;
13pub mod tcp_conn;
14pub mod udp_conn;
15
16pub use conn_info::ConnInfo;
17
18use self::tcp_conn::TcpConn;
19use crate::conntrack::conn::udp_conn::UdpConn;
20use crate::conntrack::pdu::{L4Context, L4Pdu};
21use crate::lcore::CoreId;
22use crate::protocols::packet::tcp::{ACK, RST, SYN};
23use crate::protocols::stream::ParserRegistry;
24use crate::stats::{
25 StatExt, DROPPED_MIDDLE_OF_CONNECTION_TCP_BYTE, DROPPED_MIDDLE_OF_CONNECTION_TCP_PKT,
26};
27use crate::subscription::{Subscription, Trackable};
28
29use anyhow::{bail, Result};
30use std::time::Instant;
31
32pub(crate) enum L4Conn {
36 Tcp(TcpConn),
37 Udp(UdpConn),
38}
39
40pub(crate) struct Conn<T>
42where
43 T: Trackable,
44{
45 pub(crate) last_seen_ts: Instant,
47 pub(crate) inactivity_window: usize,
49 pub(crate) l4conn: L4Conn,
51 pub(crate) info: ConnInfo<T>,
53}
54
55impl<T> Conn<T>
56where
57 T: Trackable,
58{
59 pub(super) fn new_tcp(
64 initial_timeout: usize,
65 max_ooo: usize,
66 pdu: &L4Pdu,
67 core_id: CoreId,
68 ) -> Result<Self> {
69 let tcp_conn = if pdu.ctxt.flags & SYN != 0
70 && pdu.ctxt.flags & ACK == 0
71 && pdu.ctxt.flags & RST == 0
72 {
73 TcpConn::new_on_syn(pdu.ctxt, max_ooo)
74 } else {
75 DROPPED_MIDDLE_OF_CONNECTION_TCP_PKT.inc();
76 DROPPED_MIDDLE_OF_CONNECTION_TCP_BYTE.inc_by(pdu.mbuf.data_len() as u64);
77 bail!("Not SYN")
78 };
79 Ok(Conn {
80 last_seen_ts: pdu.ts,
81 inactivity_window: initial_timeout,
82 l4conn: L4Conn::Tcp(tcp_conn),
83 info: ConnInfo::new(pdu, core_id),
84 })
85 }
86
87 #[allow(clippy::unnecessary_wraps)]
90 pub(super) fn new_udp(initial_timeout: usize, pdu: &L4Pdu, core_id: CoreId) -> Result<Self> {
91 let udp_conn = UdpConn;
92 Ok(Conn {
93 last_seen_ts: pdu.ts,
94 inactivity_window: initial_timeout,
95 l4conn: L4Conn::Udp(udp_conn),
96 info: ConnInfo::new(pdu, core_id),
97 })
98 }
99
100 #[allow(dead_code)]
101 pub(super) fn flow_len(&self, dir: bool) -> Option<usize> {
102 match &self.l4conn {
103 L4Conn::Tcp(tcp_conn) => Some(tcp_conn.flow_len(dir)),
104 L4Conn::Udp(_) => None,
105 }
106 }
107
108 #[allow(dead_code)]
109 pub(super) fn total_len(&self) -> Option<usize> {
110 match &self.l4conn {
111 L4Conn::Tcp(tcp_conn) => Some(tcp_conn.total_len()),
112 L4Conn::Udp(_) => None,
113 }
114 }
115
116 pub(super) fn update(
118 &mut self,
119 mut pdu: L4Pdu,
120 subscription: &Subscription<T::Subscribed>,
121 registry: &ParserRegistry,
122 ) {
123 if self.info.linfo.actions.needs_update() {
125 self.info.new_packet(&pdu, subscription);
126 }
127
128 if !self.info.needs_reassembly() {
131 self.update_tcp_flags(pdu.flags(), pdu.dir);
132 return;
133 }
134
135 match &mut self.l4conn {
137 L4Conn::Tcp(tcp_conn) => {
138 tcp_conn.reassemble(pdu, &mut self.info, subscription, registry);
139 if !self.info.needs_reassembly() {
142 if !tcp_conn.ctos.ooo_buf.is_empty() {
144 tcp_conn.ctos.ooo_buf.buf.clear();
145 }
146 if !tcp_conn.stoc.ooo_buf.is_empty() {
147 tcp_conn.stoc.ooo_buf.buf.clear();
148 }
149 }
150 }
151 L4Conn::Udp(_) => self.info.consume_stream(&mut pdu, subscription, registry),
152 }
153 }
154
155 #[inline]
157 pub(super) fn update_tcp_flags(&mut self, flags: u8, dir: bool) {
158 if let L4Conn::Tcp(tcp_conn) = &mut self.l4conn {
159 tcp_conn.update_flags(flags, dir);
160 }
161 }
162
163 pub(super) fn remove_from_table(&self) -> bool {
170 match &self.l4conn {
171 L4Conn::Udp(_) => false,
172 _ => self.info.drop(),
173 }
174 }
175
176 pub(super) fn drop_pdu(&self) -> bool {
182 self.info.drop()
183 }
184
185 pub(super) fn terminated(&self) -> bool {
187 match &self.l4conn {
188 L4Conn::Tcp(tcp_conn) => tcp_conn.is_terminated(),
189 L4Conn::Udp(_udp_conn) => false,
190 }
191 }
192
193 pub(super) fn packet_dir(&self, ctxt: &L4Context) -> bool {
196 self.info.cdata.five_tuple.orig == ctxt.src
197 }
198
199 pub(crate) fn terminate(&mut self, subscription: &Subscription<T::Subscribed>) {
205 self.info.handle_terminate(subscription);
206 }
207}