Skip to main content

net_wire/icmpv4/
message.rs

1//! ICMPv4 checked borrowed message views.
2
3use super::types::Icmpv4Type;
4use crate::{error::ParseError, internet_checksum};
5
6pub(super) const HEADER_LENGTH: usize = 4;
7
8/// A structurally validated ICMPv4 message.
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub struct Icmpv4Message<'a> {
11    bytes: &'a [u8],
12}
13impl<'a> Icmpv4Message<'a> {
14    /// Parses a complete ICMPv4 message, without accepting or rejecting its checksum.
15    pub fn parse(bytes: &'a [u8]) -> Result<Self, ParseError> {
16        if bytes.len() < HEADER_LENGTH {
17            return Err(ParseError::Truncated {
18                minimum: HEADER_LENGTH,
19                available: bytes.len(),
20            });
21        }
22        Ok(Self { bytes })
23    }
24    /// Returns the message type.
25    pub fn message_type(&self) -> Icmpv4Type {
26        Icmpv4Type::new(self.bytes[0])
27    }
28    /// Returns the message code.
29    pub fn code(&self) -> u8 {
30        self.bytes[1]
31    }
32    /// Returns the encoded checksum.
33    pub fn checksum(&self) -> u16 {
34        u16::from_be_bytes([self.bytes[2], self.bytes[3]])
35    }
36    /// Returns body bytes after the common header.
37    pub fn body(&self) -> &'a [u8] {
38        &self.bytes[HEADER_LENGTH..]
39    }
40    /// Returns the represented message bytes.
41    pub fn as_bytes(&self) -> &'a [u8] {
42        self.bytes
43    }
44    /// Tests the complete message checksum.
45    pub fn checksum_is_valid(&self) -> bool {
46        internet_checksum::sum(self.bytes) == 0xffff
47    }
48}
49
50/// A mutable structurally validated ICMPv4 message.
51#[derive(Debug, Eq, PartialEq)]
52pub struct Icmpv4MessageMut<'a> {
53    bytes: &'a mut [u8],
54}
55impl<'a> Icmpv4MessageMut<'a> {
56    /// Parses a complete ICMPv4 message, without accepting or rejecting its checksum.
57    pub fn parse(bytes: &'a mut [u8]) -> Result<Self, ParseError> {
58        if bytes.len() < HEADER_LENGTH {
59            return Err(ParseError::Truncated {
60                minimum: HEADER_LENGTH,
61                available: bytes.len(),
62            });
63        }
64        Ok(Self { bytes })
65    }
66    pub(crate) fn from_validated(bytes: &'a mut [u8]) -> Self {
67        Self { bytes }
68    }
69    /// Returns the message type.
70    pub fn message_type(&self) -> Icmpv4Type {
71        Icmpv4Type::new(self.bytes[0])
72    }
73    /// Returns the message code.
74    pub fn code(&self) -> u8 {
75        self.bytes[1]
76    }
77    /// Returns the encoded checksum.
78    pub fn checksum(&self) -> u16 {
79        u16::from_be_bytes([self.bytes[2], self.bytes[3]])
80    }
81    /// Returns body bytes.
82    pub fn body(&self) -> &[u8] {
83        &self.bytes[HEADER_LENGTH..]
84    }
85    /// Returns mutable body bytes without updating the checksum.
86    pub fn body_mut(&mut self) -> &mut [u8] {
87        &mut self.bytes[HEADER_LENGTH..]
88    }
89    /// Returns represented bytes.
90    pub fn as_bytes(&self) -> &[u8] {
91        self.bytes
92    }
93    /// Returns represented bytes mutably.
94    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
95        self.bytes
96    }
97    /// Replaces type without updating checksum.
98    pub fn set_message_type(&mut self, value: Icmpv4Type) {
99        self.bytes[0] = value.raw();
100    }
101    /// Replaces code without updating checksum.
102    pub fn set_code(&mut self, value: u8) {
103        self.bytes[1] = value;
104    }
105    /// Replaces checksum directly.
106    pub fn set_checksum(&mut self, value: u16) {
107        self.bytes[2..4].copy_from_slice(&value.to_be_bytes());
108    }
109    /// Recomputes the complete ICMPv4 checksum.
110    pub fn update_checksum(&mut self) {
111        self.bytes[2..4].fill(0);
112        let value = internet_checksum::checksum(internet_checksum::add_bytes(0, self.bytes));
113        self.set_checksum(value);
114    }
115    /// Tests the complete ICMPv4 checksum.
116    pub fn checksum_is_valid(&self) -> bool {
117        internet_checksum::sum(self.bytes) == 0xffff
118    }
119}