retina_core/conntrack/
pdu.rs1use crate::memory::mbuf::Mbuf;
2use crate::protocols::packet::ethernet::Ethernet;
3use crate::protocols::packet::ipv4::Ipv4;
4use crate::protocols::packet::ipv6::Ipv6;
5use crate::protocols::packet::tcp::{Tcp, TCP_PROTOCOL};
6use crate::protocols::packet::udp::{Udp, UDP_PROTOCOL};
7use crate::protocols::packet::Packet;
8
9use anyhow::{bail, Result};
10
11use std::net::{IpAddr, SocketAddr};
12
13#[derive(Debug)]
15pub struct L4Pdu {
16 pub(crate) mbuf: Mbuf,
18 pub(crate) ctxt: L4Context,
20 pub(crate) dir: bool,
22}
23
24impl L4Pdu {
25 pub(crate) fn new(mbuf: Mbuf, ctxt: L4Context, dir: bool) -> Self {
26 L4Pdu { mbuf, ctxt, dir }
27 }
28
29 #[inline]
30 pub(crate) fn mbuf_own(self) -> Mbuf {
31 self.mbuf
32 }
33
34 #[inline]
35 pub(crate) fn mbuf_ref(&self) -> &Mbuf {
36 &self.mbuf
37 }
38
39 #[inline]
40 pub(crate) fn offset(&self) -> usize {
41 self.ctxt.offset
42 }
43
44 #[inline]
45 pub(crate) fn length(&self) -> usize {
46 self.ctxt.length
47 }
48
49 #[inline]
50 pub(crate) fn seq_no(&self) -> u32 {
51 self.ctxt.seq_no
52 }
53
54 #[inline]
55 pub(crate) fn flags(&self) -> u8 {
56 self.ctxt.flags
57 }
58}
59
60#[derive(Debug, Clone, Copy)]
62pub struct L4Context {
63 pub(crate) src: SocketAddr,
65 pub(crate) dst: SocketAddr,
67 pub(crate) proto: usize,
69 pub(crate) idx: usize,
71 pub(crate) offset: usize,
73 pub(crate) length: usize,
75 pub(crate) seq_no: u32,
77 pub(crate) flags: u8,
79}
80
81impl L4Context {
82 pub(crate) fn new(mbuf: &Mbuf, idx: usize) -> Result<Self> {
83 if let Ok(eth) = mbuf.parse_to::<Ethernet>() {
84 if let Ok(ipv4) = eth.parse_to::<Ipv4>() {
85 if let Ok(tcp) = ipv4.parse_to::<Tcp>() {
86 if let Some(payload_size) = (ipv4.total_length() as usize)
87 .checked_sub(ipv4.header_len() + tcp.header_len())
88 {
89 Ok(L4Context {
90 src: SocketAddr::new(IpAddr::V4(ipv4.src_addr()), tcp.src_port()),
91 dst: SocketAddr::new(IpAddr::V4(ipv4.dst_addr()), tcp.dst_port()),
92 proto: TCP_PROTOCOL,
93 idx,
94 offset: tcp.next_header_offset(),
95 length: payload_size,
96 seq_no: tcp.seq_no(),
97 flags: tcp.flags(),
98 })
99 } else {
100 bail!("Malformed Packet");
101 }
102 } else if let Ok(udp) = ipv4.parse_to::<Udp>() {
103 if let Some(payload_size) = (ipv4.total_length() as usize)
104 .checked_sub(ipv4.header_len() + udp.header_len())
105 {
106 Ok(L4Context {
107 src: SocketAddr::new(IpAddr::V4(ipv4.src_addr()), udp.src_port()),
108 dst: SocketAddr::new(IpAddr::V4(ipv4.dst_addr()), udp.dst_port()),
109 proto: UDP_PROTOCOL,
110 idx,
111 offset: udp.next_header_offset(),
112 length: payload_size,
113 seq_no: 0,
114 flags: 0,
115 })
116 } else {
117 bail!("Malformed Packet");
118 }
119 } else {
120 bail!("Not TCP or UDP");
121 }
122 } else if let Ok(ipv6) = eth.parse_to::<Ipv6>() {
123 if let Ok(tcp) = ipv6.parse_to::<Tcp>() {
124 if let Some(payload_size) =
125 (ipv6.payload_length() as usize).checked_sub(tcp.header_len())
126 {
127 Ok(L4Context {
128 src: SocketAddr::new(IpAddr::V6(ipv6.src_addr()), tcp.src_port()),
129 dst: SocketAddr::new(IpAddr::V6(ipv6.dst_addr()), tcp.dst_port()),
130 proto: TCP_PROTOCOL,
131 idx,
132 offset: tcp.next_header_offset(),
133 length: payload_size,
134 seq_no: tcp.seq_no(),
135 flags: tcp.flags(),
136 })
137 } else {
138 bail!("Malformed Packet");
139 }
140 } else if let Ok(udp) = ipv6.parse_to::<Udp>() {
141 if let Some(payload_size) =
142 (ipv6.payload_length() as usize).checked_sub(udp.header_len())
143 {
144 Ok(L4Context {
145 src: SocketAddr::new(IpAddr::V6(ipv6.src_addr()), udp.src_port()),
146 dst: SocketAddr::new(IpAddr::V6(ipv6.dst_addr()), udp.dst_port()),
147 proto: UDP_PROTOCOL,
148 idx,
149 offset: udp.next_header_offset(),
150 length: payload_size,
151 seq_no: 0,
152 flags: 0,
153 })
154 } else {
155 bail!("Malformed Packet");
156 }
157 } else {
158 bail!("Not TCP or UDP");
159 }
160 } else {
161 bail!("Not IP");
162 }
163 } else {
164 bail!("Not Ethernet");
165 }
166 }
167}