zero_packet/network/extensions/
fragment.rs

1use core::fmt;
2
3/// The length of a Fragment extension header in bytes.
4pub const FRAGMENT_HEADER_LENGTH: usize = 8;
5
6/// Writes the Fragment header fields.
7pub struct FragmentHeaderWriter<'a> {
8    pub bytes: &'a mut [u8],
9}
10
11impl<'a> FragmentHeaderWriter<'a> {
12    /// Creates a new `FragmentHeaderWriter` from the given data slice.
13    #[inline]
14    pub fn new(bytes: &'a mut [u8]) -> Result<Self, &'static str> {
15        if bytes.len() < FRAGMENT_HEADER_LENGTH {
16            panic!("Slice is too short to contain a Fragment header.");
17        }
18
19        Ok(Self { bytes })
20    }
21
22    /// Returns the length of the Fragment header.
23    #[inline]
24    pub fn header_len(&self) -> usize {
25        FRAGMENT_HEADER_LENGTH
26    }
27
28    /// Sets the next header field.
29    ///
30    /// Identifies the type of the next header.
31    #[inline]
32    pub fn set_next_header(&mut self, next_header: u8) {
33        self.bytes[0] = next_header;
34    }
35
36    /// Sets the reserved field.
37    ///
38    /// Should be all zeroes.
39    #[inline]
40    pub fn set_reserved(&mut self, reserved: u8) {
41        self.bytes[1] = reserved;
42    }
43
44    /// Sets the fragment offset field.
45    ///
46    /// Offset in 8 bytes relative to the start of the fragmentable part of the original packet.
47    #[inline]
48    pub fn set_fragment_offset(&mut self, fragment_offset: u16) {
49        // All 8 bits of the 2nd byte and the first 5 bits of the 3rd byte.
50        let value = fragment_offset & 0x1FFF;
51        self.bytes[2] = (value >> 5) as u8;
52        self.bytes[3] = (self.bytes[3] & 0xE0) | ((value & 0x1F) as u8);
53    }
54
55    /// Sets the res field.
56    ///
57    /// Reserved and should be all zeroes.
58    #[inline]
59    pub fn set_res(&mut self, res: u8) {
60        // Bits 5-6 of the 3rd byte.
61        let value = res & 0b11;
62        self.bytes[3] = (self.bytes[3] & 0x9F) | (value << 5);
63    }
64
65    /// Sets the M flag.
66    ///
67    /// 1 means more fragments follow, 0 means this is the last fragment.
68    #[inline]
69    pub fn set_m_flag(&mut self, m_flag: bool) {
70        // Bit 7 of the 3rd byte.
71        if m_flag {
72            self.bytes[3] |= 0x80;
73        } else {
74            self.bytes[3] &= 0x7F;
75        }
76    }
77
78    /// Sets the identification field.
79    ///
80    /// Identifies the packet, generated by the sender, to help the receiver reassemble the fragments.
81    #[inline]
82    pub fn set_identification(&mut self, identification: u32) {
83        self.bytes[4] = (identification >> 24) as u8;
84        self.bytes[5] = (identification >> 16) as u8;
85        self.bytes[6] = (identification >> 8) as u8;
86        self.bytes[7] = identification as u8;
87    }
88}
89
90/// Reads the Fragment header fields.
91pub struct FragmentHeaderReader<'a> {
92    pub bytes: &'a [u8],
93}
94
95impl<'a> FragmentHeaderReader<'a> {
96    #[inline]
97    pub fn new(bytes: &'a [u8]) -> Result<Self, &'static str> {
98        if bytes.len() < FRAGMENT_HEADER_LENGTH {
99            return Err("Slice is too short to contain a Fragment header.");
100        }
101
102        Ok(Self { bytes })
103    }
104
105    /// Returns the next header field.
106    ///
107    /// Identifies the type of the next header.
108    #[inline]
109    pub fn next_header(&self) -> u8 {
110        self.bytes[0]
111    }
112
113    /// Returns the reserved field.
114    ///
115    /// Should be all zeroes.
116    #[inline]
117    pub fn reserved(&self) -> u8 {
118        self.bytes[1]
119    }
120
121    /// Returns the fragment offset field.
122    ///
123    /// Offset in 8 bytes relative to the start of the fragmentable part of the original packet.
124    #[inline]
125    pub fn fragment_offset(&self) -> u16 {
126        ((self.bytes[2] as u16) << 5) | ((self.bytes[3] & 0x1F) as u16)
127    }
128
129    /// Returns the res field.
130    ///
131    /// Reserved and should be all zeroes.
132    #[inline]
133    pub fn res(&self) -> u8 {
134        (self.bytes[3] >> 5) & 0b11
135    }
136
137    /// Returns the M flag.
138    ///
139    /// 1 means more fragments follow, 0 means this is the last fragment.
140    #[inline]
141    pub fn m_flag(&self) -> bool {
142        (self.bytes[3] & 0x80) != 0
143    }
144
145    /// Returns the identification field.
146    ///
147    /// Identifies the packet, generated by the sender, to help the receiver reassemble the fragments.
148    #[inline]
149    pub fn identification(&self) -> u32 {
150        ((self.bytes[4] as u32) << 24)
151            | ((self.bytes[5] as u32) << 16)
152            | ((self.bytes[6] as u32) << 8)
153            | (self.bytes[7] as u32)
154    }
155
156    /// Returns the length of the Fragment header.
157    #[inline]
158    pub fn header_len(&self) -> usize {
159        FRAGMENT_HEADER_LENGTH
160    }
161
162    /// Returns a reference to the header.
163    #[inline]
164    pub fn header(&self) -> &'a [u8] {
165        &self.bytes[..FRAGMENT_HEADER_LENGTH]
166    }
167
168    /// Returns a reference to the payload.
169    #[inline]
170    pub fn payload(&self) -> &'a [u8] {
171        &self.bytes[FRAGMENT_HEADER_LENGTH..]
172    }
173}
174
175impl fmt::Debug for FragmentHeaderReader<'_> {
176    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177        f.debug_struct("FragmentHeader")
178            .field("next_header", &self.next_header())
179            .field("reserved", &self.reserved())
180            .field("fragment_offset", &self.fragment_offset())
181            .field("res", &self.res())
182            .field("m_flag", &self.m_flag())
183            .field("identification", &self.identification())
184            .finish()
185    }
186}
187
188#[cfg(test)]
189pub mod tests {
190    use super::*;
191
192    #[test]
193    fn getters_and_setters() {
194        // Raw packet.
195        let mut bytes = [0u8; 16];
196
197        // Random values.
198        let next_header = 6;
199        let reserved = 0;
200        let fragment_offset = 255;
201        let res = 0;
202        let m_flag = true;
203        let identification = 0x04050607;
204
205        // Create a new Fragment header.
206        let mut writer = FragmentHeaderWriter::new(&mut bytes).unwrap();
207
208        // Set the fields.
209        writer.set_next_header(next_header);
210        writer.set_reserved(reserved);
211        writer.set_fragment_offset(fragment_offset);
212        writer.set_res(res);
213        writer.set_m_flag(m_flag);
214        writer.set_identification(identification);
215
216        // Create a Fragment header reader.
217        let reader = FragmentHeaderReader::new(&bytes).unwrap();
218
219        // Check the fields.
220        assert_eq!(reader.next_header(), next_header);
221        assert_eq!(reader.reserved(), reserved);
222        assert_eq!(reader.fragment_offset(), fragment_offset);
223        assert_eq!(reader.res(), res);
224        assert_eq!(reader.m_flag(), m_flag);
225        assert_eq!(reader.identification(), identification);
226    }
227}