iris_core/protocols/packet/
ipv4.rs1use crate::memory::mbuf::Mbuf;
4use crate::protocols::packet::{Packet, PacketHeader, PacketParseError};
5use crate::utils::types::*;
6
7use std::net::Ipv4Addr;
8
9const IPV4_PROTOCOL: usize = 0x0800;
11const IPV4_RF: u16 = 0x8000;
13const IPV4_DF: u16 = 0x4000;
15const IPV4_MF: u16 = 0x2000;
17const IPV4_FRAG_OFFSET: u16 = 0x1FFF;
19
20#[derive(Debug)]
24pub struct Ipv4<'a> {
25 header: Ipv4Header,
27 offset: usize,
29 mbuf: &'a Mbuf,
31}
32
33impl Ipv4<'_> {
34 #[inline]
36 pub fn version(&self) -> u8 {
37 (self.header.version_ihl & 0xf0) >> 4
38 }
39
40 #[inline]
42 pub fn ihl(&self) -> u8 {
43 self.header.version_ihl & 0x0f
44 }
45
46 #[inline]
48 pub fn version_ihl(&self) -> u8 {
49 self.header.version_ihl
50 }
51
52 #[inline]
54 pub fn dscp(&self) -> u8 {
55 self.header.dscp_ecn >> 2
56 }
57
58 #[inline]
60 pub fn ecn(&self) -> u8 {
61 self.header.dscp_ecn & 0x03
62 }
63
64 #[inline]
66 pub fn dscp_ecn(&self) -> u8 {
67 self.header.dscp_ecn
68 }
69
70 #[inline]
72 pub fn type_of_service(&self) -> u8 {
73 self.dscp_ecn()
74 }
75
76 #[inline]
78 pub fn total_length(&self) -> u16 {
79 self.header.total_length.into()
80 }
81
82 #[inline]
84 pub fn identification(&self) -> u16 {
85 self.header.identification.into()
86 }
87
88 #[inline]
90 pub fn flags_to_fragment_offset(&self) -> u16 {
91 self.header.flags_to_fragment_offset.into()
92 }
93
94 #[inline]
96 pub fn flags(&self) -> u8 {
97 (self.flags_to_fragment_offset() >> 13) as u8
98 }
99
100 #[inline]
102 pub fn rf(&self) -> bool {
103 (self.flags_to_fragment_offset() & IPV4_RF) != 0
104 }
105
106 #[inline]
108 pub fn df(&self) -> bool {
109 (self.flags_to_fragment_offset() & IPV4_DF) != 0
110 }
111
112 #[inline]
114 pub fn mf(&self) -> bool {
115 (self.flags_to_fragment_offset() & IPV4_MF) != 0
116 }
117
118 #[inline]
120 pub fn fragment_offset(&self) -> u16 {
121 self.flags_to_fragment_offset() & IPV4_FRAG_OFFSET
122 }
123
124 #[inline]
126 pub fn time_to_live(&self) -> u8 {
127 self.header.time_to_live
128 }
129
130 #[inline]
132 pub fn protocol(&self) -> u8 {
133 self.header.protocol
134 }
135
136 #[inline]
138 pub fn header_checksum(&self) -> u16 {
139 self.header.header_checksum.into()
140 }
141
142 #[inline]
144 pub fn src_addr(&self) -> Ipv4Addr {
145 self.header.src_addr
146 }
147
148 #[inline]
150 pub fn dst_addr(&self) -> Ipv4Addr {
151 self.header.dst_addr
152 }
153}
154
155impl<'a> Packet<'a> for Ipv4<'a> {
156 fn mbuf(&self) -> &Mbuf {
157 self.mbuf
158 }
159
160 fn header_len(&self) -> usize {
161 self.header.length()
162 }
163
164 fn next_header_offset(&self) -> usize {
165 self.offset + self.header_len()
166 }
167
168 fn next_header(&self) -> Option<usize> {
169 Some(self.protocol().into())
170 }
171
172 fn parse_from(outer: &'a impl Packet<'a>) -> Result<Self, PacketParseError>
173 where
174 Self: Sized,
175 {
176 let offset = outer.next_header_offset();
177 if let Ok(header) = outer.mbuf().get_data(offset) {
178 match outer.next_header() {
179 Some(IPV4_PROTOCOL) => Ok(Ipv4 {
180 header: unsafe { *header },
181 offset,
182 mbuf: outer.mbuf(),
183 }),
184 _ => Err(PacketParseError::InvalidProtocol),
185 }
186 } else {
187 Err(PacketParseError::InvalidRead)
188 }
189 }
190}
191
192#[derive(Debug, Clone, Copy)]
194#[repr(C, packed)]
195struct Ipv4Header {
196 version_ihl: u8,
197 dscp_ecn: u8,
198 total_length: u16be,
199 identification: u16be,
200 flags_to_fragment_offset: u16be,
201 time_to_live: u8,
202 protocol: u8,
203 header_checksum: u16be,
204 src_addr: Ipv4Addr,
205 dst_addr: Ipv4Addr,
206}
207
208impl PacketHeader for Ipv4Header {
209 fn length(&self) -> usize {
214 ((self.version_ihl & 0xf) << 2).into()
215 }
216}