Skip to main content

net_wire/tcp/
segment.rs

1//! Checked borrowed TCP segment views.
2
3use super::flags::TcpFlags;
4use crate::error::ParseError;
5
6pub(super) const HEADER_LENGTH: usize = 20;
7
8/// A structurally validated TCP segment.
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub struct TcpSegment<'a> {
11    bytes: &'a [u8],
12}
13
14impl<'a> TcpSegment<'a> {
15    /// Parses a complete TCP segment without checking its checksum.
16    #[inline]
17    pub fn parse(bytes: &'a [u8]) -> Result<Self, ParseError> {
18        validate(bytes)?;
19        Ok(Self { bytes })
20    }
21
22    /// Returns the source port.
23    #[inline]
24    pub fn source_port(&self) -> u16 {
25        u16::from_be_bytes([self.bytes[0], self.bytes[1]])
26    }
27
28    /// Returns the destination port.
29    #[inline]
30    pub fn destination_port(&self) -> u16 {
31        u16::from_be_bytes([self.bytes[2], self.bytes[3]])
32    }
33
34    /// Returns the sequence number.
35    #[inline]
36    pub fn sequence_number(&self) -> u32 {
37        u32::from_be_bytes(self.bytes[4..8].try_into().expect("validated TCP header"))
38    }
39
40    /// Returns the acknowledgment number.
41    #[inline]
42    pub fn acknowledgment_number(&self) -> u32 {
43        u32::from_be_bytes(self.bytes[8..12].try_into().expect("validated TCP header"))
44    }
45
46    /// Returns the data offset in four-octet words.
47    #[inline]
48    pub fn data_offset(&self) -> u8 {
49        self.bytes[12] >> 4
50    }
51
52    /// Returns the header length in octets.
53    #[inline]
54    pub fn header_length(&self) -> usize {
55        usize::from(self.data_offset()) * 4
56    }
57
58    /// Returns the four reserved header bits.
59    #[inline]
60    pub fn reserved(&self) -> u8 {
61        self.bytes[12] & 0x0f
62    }
63
64    /// Returns TCP control flags with their raw wire value preserved.
65    #[inline]
66    pub fn flags(&self) -> TcpFlags {
67        TcpFlags::new(self.bytes[13])
68    }
69
70    /// Returns the window size.
71    #[inline]
72    pub fn window_size(&self) -> u16 {
73        u16::from_be_bytes([self.bytes[14], self.bytes[15]])
74    }
75
76    /// Returns the encoded checksum.
77    #[inline]
78    pub fn checksum(&self) -> u16 {
79        u16::from_be_bytes([self.bytes[16], self.bytes[17]])
80    }
81
82    /// Returns the urgent pointer.
83    #[inline]
84    pub fn urgent_pointer(&self) -> u16 {
85        u16::from_be_bytes([self.bytes[18], self.bytes[19]])
86    }
87
88    /// Returns header options.
89    #[inline]
90    pub fn options(&self) -> &'a [u8] {
91        &self.bytes[HEADER_LENGTH..self.header_length()]
92    }
93
94    /// Returns payload bytes.
95    #[inline]
96    pub fn payload(&self) -> &'a [u8] {
97        &self.bytes[self.header_length()..]
98    }
99
100    /// Returns all represented segment bytes.
101    #[inline]
102    pub fn as_bytes(&self) -> &'a [u8] {
103        self.bytes
104    }
105}
106
107/// A mutable structurally validated TCP segment.
108#[derive(Debug, Eq, PartialEq)]
109pub struct TcpSegmentMut<'a> {
110    bytes: &'a mut [u8],
111}
112
113impl<'a> TcpSegmentMut<'a> {
114    /// Parses a complete TCP segment without checking its checksum.
115    #[inline]
116    pub fn parse(bytes: &'a mut [u8]) -> Result<Self, ParseError> {
117        validate(bytes)?;
118        Ok(Self { bytes })
119    }
120
121    pub(crate) fn from_validated(bytes: &'a mut [u8]) -> Self {
122        Self { bytes }
123    }
124
125    /// Returns the source port.
126    #[inline]
127    pub fn source_port(&self) -> u16 {
128        u16::from_be_bytes([self.bytes[0], self.bytes[1]])
129    }
130
131    /// Returns the destination port.
132    #[inline]
133    pub fn destination_port(&self) -> u16 {
134        u16::from_be_bytes([self.bytes[2], self.bytes[3]])
135    }
136
137    /// Returns the sequence number.
138    #[inline]
139    pub fn sequence_number(&self) -> u32 {
140        u32::from_be_bytes(self.bytes[4..8].try_into().expect("validated TCP header"))
141    }
142
143    /// Returns the acknowledgment number.
144    #[inline]
145    pub fn acknowledgment_number(&self) -> u32 {
146        u32::from_be_bytes(self.bytes[8..12].try_into().expect("validated TCP header"))
147    }
148
149    /// Returns the data offset in four-octet words.
150    #[inline]
151    pub fn data_offset(&self) -> u8 {
152        self.bytes[12] >> 4
153    }
154
155    /// Returns the header length in octets.
156    #[inline]
157    pub fn header_length(&self) -> usize {
158        usize::from(self.data_offset()) * 4
159    }
160
161    /// Returns the four reserved header bits.
162    #[inline]
163    pub fn reserved(&self) -> u8 {
164        self.bytes[12] & 0x0f
165    }
166
167    /// Returns TCP control flags with their raw wire value preserved.
168    #[inline]
169    pub fn flags(&self) -> TcpFlags {
170        TcpFlags::new(self.bytes[13])
171    }
172
173    /// Returns the window size.
174    #[inline]
175    pub fn window_size(&self) -> u16 {
176        u16::from_be_bytes([self.bytes[14], self.bytes[15]])
177    }
178
179    /// Returns the encoded checksum.
180    #[inline]
181    pub fn checksum(&self) -> u16 {
182        u16::from_be_bytes([self.bytes[16], self.bytes[17]])
183    }
184
185    /// Returns the urgent pointer.
186    #[inline]
187    pub fn urgent_pointer(&self) -> u16 {
188        u16::from_be_bytes([self.bytes[18], self.bytes[19]])
189    }
190
191    /// Returns header options.
192    #[inline]
193    pub fn options(&self) -> &[u8] {
194        &self.bytes[HEADER_LENGTH..self.header_length()]
195    }
196
197    /// Returns mutable header options without updating the checksum.
198    #[inline]
199    pub fn options_mut(&mut self) -> &mut [u8] {
200        let header_length = self.header_length();
201        &mut self.bytes[HEADER_LENGTH..header_length]
202    }
203
204    /// Returns payload bytes.
205    #[inline]
206    pub fn payload(&self) -> &[u8] {
207        &self.bytes[self.header_length()..]
208    }
209
210    /// Returns mutable payload bytes without updating the checksum.
211    #[inline]
212    pub fn payload_mut(&mut self) -> &mut [u8] {
213        let header_length = self.header_length();
214        &mut self.bytes[header_length..]
215    }
216
217    /// Returns all represented segment bytes.
218    #[inline]
219    pub fn as_bytes(&self) -> &[u8] {
220        self.bytes
221    }
222
223    /// Returns all represented segment bytes mutably without updating the checksum.
224    #[inline]
225    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
226        self.bytes
227    }
228
229    /// Replaces the source port without updating the checksum.
230    #[inline]
231    pub fn set_source_port(&mut self, value: u16) {
232        self.bytes[0..2].copy_from_slice(&value.to_be_bytes());
233    }
234
235    /// Replaces the destination port without updating the checksum.
236    #[inline]
237    pub fn set_destination_port(&mut self, value: u16) {
238        self.bytes[2..4].copy_from_slice(&value.to_be_bytes());
239    }
240
241    /// Replaces the sequence number without updating the checksum.
242    #[inline]
243    pub fn set_sequence_number(&mut self, value: u32) {
244        self.bytes[4..8].copy_from_slice(&value.to_be_bytes());
245    }
246
247    /// Replaces the acknowledgment number without updating the checksum.
248    #[inline]
249    pub fn set_acknowledgment_number(&mut self, value: u32) {
250        self.bytes[8..12].copy_from_slice(&value.to_be_bytes());
251    }
252
253    /// Replaces flags without updating the checksum.
254    #[inline]
255    pub fn set_flags(&mut self, value: TcpFlags) {
256        self.bytes[13] = value.raw();
257    }
258
259    /// Replaces the window size without updating the checksum.
260    #[inline]
261    pub fn set_window_size(&mut self, value: u16) {
262        self.bytes[14..16].copy_from_slice(&value.to_be_bytes());
263    }
264
265    /// Replaces the checksum directly.
266    #[inline]
267    pub fn set_checksum(&mut self, value: u16) {
268        self.bytes[16..18].copy_from_slice(&value.to_be_bytes());
269    }
270
271    /// Replaces the urgent pointer without updating the checksum.
272    #[inline]
273    pub fn set_urgent_pointer(&mut self, value: u16) {
274        self.bytes[18..20].copy_from_slice(&value.to_be_bytes());
275    }
276}
277
278fn validate(bytes: &[u8]) -> Result<(), ParseError> {
279    if bytes.len() < HEADER_LENGTH {
280        return Err(ParseError::Truncated {
281            minimum: HEADER_LENGTH,
282            available: bytes.len(),
283        });
284    }
285    let header_length = usize::from(bytes[12] >> 4) * 4;
286    if header_length < HEADER_LENGTH {
287        return Err(ParseError::InvalidHeaderLength {
288            minimum: HEADER_LENGTH,
289            actual: header_length,
290        });
291    }
292    if bytes.len() < header_length {
293        return Err(ParseError::Truncated {
294            minimum: header_length,
295            available: bytes.len(),
296        });
297    }
298    Ok(())
299}