iris_core/conntrack/
pdu.rs1use crate::memory::mbuf::Mbuf;
5use crate::protocols::packet::ethernet::Ethernet;
6use crate::protocols::packet::ipv4::Ipv4;
7use crate::protocols::packet::ipv6::Ipv6;
8use crate::protocols::packet::tcp::{Tcp, TCP_PROTOCOL};
9use crate::protocols::packet::udp::{Udp, UDP_PROTOCOL};
10use crate::protocols::packet::Packet;
11
12use std::time::Instant;
13
14use anyhow::{bail, Result};
15
16use std::net::{IpAddr, SocketAddr};
17
18#[derive(Debug, Clone)]
21pub struct L4Pdu {
22 pub mbuf: Mbuf,
24 pub ctxt: L4Context,
26 pub dir: bool,
28 pub ts: Instant,
30}
31
32impl L4Pdu {
33 pub(crate) fn new(mbuf: Mbuf, ctxt: L4Context, dir: bool, ts: Instant) -> Self {
34 L4Pdu {
35 mbuf,
36 ctxt,
37 dir,
38 ts,
39 }
40 }
41
42 #[inline]
43 pub fn mbuf_own(self) -> Mbuf {
44 self.mbuf
45 }
46
47 #[inline]
48 pub fn mbuf_ref(&self) -> &Mbuf {
49 &self.mbuf
50 }
51
52 #[inline]
53 pub fn offset(&self) -> usize {
54 self.ctxt.offset
55 }
56
57 #[inline]
58 pub fn app_body_offset(&self) -> Option<usize> {
59 self.ctxt.app_offset
60 }
61
62 #[inline]
63 pub(crate) fn mark_no_payload(&mut self) {
64 self.ctxt.offset = self.mbuf.data_len();
65 self.ctxt.length = 0;
66 }
67
68 #[inline]
69 pub fn length(&self) -> usize {
70 self.ctxt.length
71 }
72
73 #[inline]
74 pub fn seq_no(&self) -> u32 {
75 self.ctxt.seq_no
76 }
77
78 #[inline]
79 pub fn ack_no(&self) -> u32 {
80 self.ctxt.ack_no
81 }
82
83 #[inline]
84 pub fn flags(&self) -> u8 {
85 self.ctxt.flags
86 }
87}
88
89#[derive(Debug, Clone, Copy)]
91pub struct L4Context {
92 pub src: SocketAddr,
94 pub dst: SocketAddr,
96 pub proto: usize,
98 pub offset: usize,
104 pub length: usize,
106 pub seq_no: u32,
108 pub ack_no: u32,
110 pub flags: u8,
112 pub reassembled: bool,
115 pub app_offset: Option<usize>,
119}
120
121impl L4Context {
122 pub fn new(mbuf: &Mbuf) -> Result<Self> {
123 if let Ok(eth) = mbuf.parse_to::<Ethernet>() {
124 if let Ok(ipv4) = eth.parse_to::<Ipv4>() {
125 if let Ok(tcp) = ipv4.parse_to::<Tcp>() {
126 if let Some(payload_size) = (ipv4.total_length() as usize)
127 .checked_sub(ipv4.header_len() + tcp.header_len())
128 {
129 Ok(L4Context {
130 src: SocketAddr::new(IpAddr::V4(ipv4.src_addr()), tcp.src_port()),
131 dst: SocketAddr::new(IpAddr::V4(ipv4.dst_addr()), tcp.dst_port()),
132 proto: TCP_PROTOCOL,
133 offset: tcp.next_header_offset(),
134 length: payload_size,
135 seq_no: tcp.seq_no(),
136 ack_no: tcp.ack_no(),
137 flags: tcp.flags(),
138 reassembled: false,
139 app_offset: None,
140 })
141 } else {
142 bail!("Malformed Packet");
143 }
144 } else if let Ok(udp) = ipv4.parse_to::<Udp>() {
145 if let Some(payload_size) = (ipv4.total_length() as usize)
146 .checked_sub(ipv4.header_len() + udp.header_len())
147 {
148 Ok(L4Context {
149 src: SocketAddr::new(IpAddr::V4(ipv4.src_addr()), udp.src_port()),
150 dst: SocketAddr::new(IpAddr::V4(ipv4.dst_addr()), udp.dst_port()),
151 proto: UDP_PROTOCOL,
152 offset: udp.next_header_offset(),
153 length: payload_size,
154 seq_no: 0,
155 ack_no: 0,
156 flags: 0,
157 reassembled: false,
158 app_offset: None,
159 })
160 } else {
161 bail!("Malformed Packet");
162 }
163 } else {
164 bail!("Not TCP or UDP");
165 }
166 } else if let Ok(ipv6) = eth.parse_to::<Ipv6>() {
167 if let Ok(tcp) = ipv6.parse_to::<Tcp>() {
168 if let Some(payload_size) =
169 (ipv6.payload_length() as usize).checked_sub(tcp.header_len())
170 {
171 Ok(L4Context {
172 src: SocketAddr::new(IpAddr::V6(ipv6.src_addr()), tcp.src_port()),
173 dst: SocketAddr::new(IpAddr::V6(ipv6.dst_addr()), tcp.dst_port()),
174 proto: TCP_PROTOCOL,
175 offset: tcp.next_header_offset(),
176 length: payload_size,
177 seq_no: tcp.seq_no(),
178 ack_no: tcp.ack_no(),
179 flags: tcp.flags(),
180 reassembled: false,
181 app_offset: None,
182 })
183 } else {
184 bail!("Malformed Packet");
185 }
186 } else if let Ok(udp) = ipv6.parse_to::<Udp>() {
187 if let Some(payload_size) =
188 (ipv6.payload_length() as usize).checked_sub(udp.header_len())
189 {
190 Ok(L4Context {
191 src: SocketAddr::new(IpAddr::V6(ipv6.src_addr()), udp.src_port()),
192 dst: SocketAddr::new(IpAddr::V6(ipv6.dst_addr()), udp.dst_port()),
193 proto: UDP_PROTOCOL,
194 offset: udp.next_header_offset(),
195 length: payload_size,
196 seq_no: 0,
197 ack_no: 0,
198 flags: 0,
199 reassembled: false,
200 app_offset: None,
201 })
202 } else {
203 bail!("Malformed Packet");
204 }
205 } else {
206 bail!("Not TCP or UDP");
207 }
208 } else {
209 bail!("Not IP");
210 }
211 } else {
212 bail!("Not Ethernet");
213 }
214 }
215}