net_wire/icmpv4/
message.rs1use super::types::Icmpv4Type;
4use crate::{error::ParseError, internet_checksum};
5
6pub(super) const HEADER_LENGTH: usize = 4;
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub struct Icmpv4Message<'a> {
11 bytes: &'a [u8],
12}
13impl<'a> Icmpv4Message<'a> {
14 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 pub fn message_type(&self) -> Icmpv4Type {
26 Icmpv4Type::new(self.bytes[0])
27 }
28 pub fn code(&self) -> u8 {
30 self.bytes[1]
31 }
32 pub fn checksum(&self) -> u16 {
34 u16::from_be_bytes([self.bytes[2], self.bytes[3]])
35 }
36 pub fn body(&self) -> &'a [u8] {
38 &self.bytes[HEADER_LENGTH..]
39 }
40 pub fn as_bytes(&self) -> &'a [u8] {
42 self.bytes
43 }
44 pub fn checksum_is_valid(&self) -> bool {
46 internet_checksum::sum(self.bytes) == 0xffff
47 }
48}
49
50#[derive(Debug, Eq, PartialEq)]
52pub struct Icmpv4MessageMut<'a> {
53 bytes: &'a mut [u8],
54}
55impl<'a> Icmpv4MessageMut<'a> {
56 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 pub fn message_type(&self) -> Icmpv4Type {
71 Icmpv4Type::new(self.bytes[0])
72 }
73 pub fn code(&self) -> u8 {
75 self.bytes[1]
76 }
77 pub fn checksum(&self) -> u16 {
79 u16::from_be_bytes([self.bytes[2], self.bytes[3]])
80 }
81 pub fn body(&self) -> &[u8] {
83 &self.bytes[HEADER_LENGTH..]
84 }
85 pub fn body_mut(&mut self) -> &mut [u8] {
87 &mut self.bytes[HEADER_LENGTH..]
88 }
89 pub fn as_bytes(&self) -> &[u8] {
91 self.bytes
92 }
93 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
95 self.bytes
96 }
97 pub fn set_message_type(&mut self, value: Icmpv4Type) {
99 self.bytes[0] = value.raw();
100 }
101 pub fn set_code(&mut self, value: u8) {
103 self.bytes[1] = value;
104 }
105 pub fn set_checksum(&mut self, value: u16) {
107 self.bytes[2..4].copy_from_slice(&value.to_be_bytes());
108 }
109 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 pub fn checksum_is_valid(&self) -> bool {
117 internet_checksum::sum(self.bytes) == 0xffff
118 }
119}