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
9use anyhow::{bail, Result};
10
11const IPV4_PROTOCOL: usize = 0x0800;
13const IPV4_RF: u16 = 0x8000;
15const IPV4_DF: u16 = 0x4000;
17const IPV4_MF: u16 = 0x2000;
19const IPV4_FRAG_OFFSET: u16 = 0x1FFF;
21
22#[derive(Debug)]
26pub struct Ipv4<'a> {
27 header: Ipv4Header,
29 offset: usize,
31 mbuf: &'a Mbuf,
33}
34
35impl Ipv4<'_> {
36 #[inline]
38 pub fn version(&self) -> u8 {
39 (self.header.version_ihl & 0xf0) >> 4
40 }
41
42 #[inline]
44 pub fn ihl(&self) -> u8 {
45 self.header.version_ihl & 0x0f
46 }
47
48 #[inline]
50 pub fn version_ihl(&self) -> u8 {
51 self.header.version_ihl
52 }
53
54 #[inline]
56 pub fn dscp(&self) -> u8 {
57 self.header.dscp_ecn >> 2
58 }
59
60 #[inline]
62 pub fn ecn(&self) -> u8 {
63 self.header.dscp_ecn & 0x03
64 }
65
66 #[inline]
68 pub fn dscp_ecn(&self) -> u8 {
69 self.header.dscp_ecn
70 }
71
72 #[inline]
74 pub fn type_of_service(&self) -> u8 {
75 self.dscp_ecn()
76 }
77
78 #[inline]
80 pub fn total_length(&self) -> u16 {
81 self.header.total_length.into()
82 }
83
84 #[inline]
86 pub fn identification(&self) -> u16 {
87 self.header.identification.into()
88 }
89
90 #[inline]
92 pub fn flags_to_fragment_offset(&self) -> u16 {
93 self.header.flags_to_fragment_offset.into()
94 }
95
96 #[inline]
98 pub fn flags(&self) -> u8 {
99 (self.flags_to_fragment_offset() >> 13) as u8
100 }
101
102 #[inline]
104 pub fn rf(&self) -> bool {
105 (self.flags_to_fragment_offset() & IPV4_RF) != 0
106 }
107
108 #[inline]
110 pub fn df(&self) -> bool {
111 (self.flags_to_fragment_offset() & IPV4_DF) != 0
112 }
113
114 #[inline]
116 pub fn mf(&self) -> bool {
117 (self.flags_to_fragment_offset() & IPV4_MF) != 0
118 }
119
120 #[inline]
122 pub fn fragment_offset(&self) -> u16 {
123 self.flags_to_fragment_offset() & IPV4_FRAG_OFFSET
124 }
125
126 #[inline]
128 pub fn time_to_live(&self) -> u8 {
129 self.header.time_to_live
130 }
131
132 #[inline]
134 pub fn protocol(&self) -> u8 {
135 self.header.protocol
136 }
137
138 #[inline]
140 pub fn header_checksum(&self) -> u16 {
141 self.header.header_checksum.into()
142 }
143
144 #[inline]
146 pub fn src_addr(&self) -> Ipv4Addr {
147 self.header.src_addr
148 }
149
150 #[inline]
152 pub fn dst_addr(&self) -> Ipv4Addr {
153 self.header.dst_addr
154 }
155}
156
157impl<'a> Packet<'a> for Ipv4<'a> {
158 fn mbuf(&self) -> &Mbuf {
159 self.mbuf
160 }
161
162 fn header_len(&self) -> usize {
163 self.header.length()
164 }
165
166 fn next_header_offset(&self) -> usize {
167 self.offset + self.header_len()
168 }
169
170 fn next_header(&self) -> Option<usize> {
171 Some(self.protocol().into())
172 }
173
174 fn parse_from(outer: &'a impl Packet<'a>) -> Result<Self>
175 where
176 Self: Sized,
177 {
178 let offset = outer.next_header_offset();
179 if let Ok(header) = outer.mbuf().get_data(offset) {
180 match outer.next_header() {
181 Some(IPV4_PROTOCOL) => Ok(Ipv4 {
182 header: unsafe { *header },
183 offset,
184 mbuf: outer.mbuf(),
185 }),
186 _ => bail!(PacketParseError::InvalidProtocol),
187 }
188 } else {
189 bail!(PacketParseError::InvalidRead)
190 }
191 }
192}
193
194#[derive(Debug, Clone, Copy)]
196#[repr(C, packed)]
197struct Ipv4Header {
198 version_ihl: u8,
199 dscp_ecn: u8,
200 total_length: u16be,
201 identification: u16be,
202 flags_to_fragment_offset: u16be,
203 time_to_live: u8,
204 protocol: u8,
205 header_checksum: u16be,
206 src_addr: Ipv4Addr,
207 dst_addr: Ipv4Addr,
208}
209
210impl PacketHeader for Ipv4Header {
211 fn length(&self) -> usize {
216 ((self.version_ihl & 0xf) << 2).into()
217 }
218}