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