net_wire/ethernet/frame.rs
1use crate::error::ParseError;
2
3use super::address::MacAddress;
4use super::ether_type::EtherType;
5
6pub(super) const HEADER_LENGTH: usize = 14;
7const DESTINATION: core::ops::Range<usize> = 0..6;
8const SOURCE: core::ops::Range<usize> = 6..12;
9const ETHER_TYPE: core::ops::Range<usize> = 12..14;
10
11/// A validated immutable borrow of one Ethernet II frame.
12///
13/// The fixed destination, source, and protocol-type header order follows
14/// [RFC 894](https://www.rfc-editor.org/rfc/rfc894). Callers must remove any frame check
15/// sequence (FCS) before parsing because every supplied byte after the fixed header is
16/// payload.
17#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18pub struct EthernetFrame<'a> {
19 bytes: &'a [u8],
20}
21
22impl<'a> EthernetFrame<'a> {
23 /// Validates and borrows an Ethernet II frame.
24 ///
25 /// The parser rejects inputs shorter than the 14-octet destination/source/type
26 /// header described by [RFC 894](https://www.rfc-editor.org/rfc/rfc894). Every
27 /// remaining supplied octet is exposed unchanged as payload; callers must remove any
28 /// frame check sequence (FCS) before parsing. No minimum payload length is imposed by
29 /// this wire view.
30 pub fn parse(bytes: &'a [u8]) -> Result<Self, ParseError> {
31 validate_frame_length(bytes.len())?;
32 Ok(Self { bytes })
33 }
34
35 /// Returns the destination Ethernet address.
36 ///
37 /// RFC 894 places the destination address in the first six octets of the Ethernet
38 /// header: <https://www.rfc-editor.org/rfc/rfc894>.
39 #[inline]
40 pub fn destination(&self) -> MacAddress {
41 MacAddress::new(
42 self.bytes[DESTINATION]
43 .try_into()
44 .expect("validated header"),
45 )
46 }
47
48 /// Returns the source Ethernet address.
49 ///
50 /// RFC 894 places the source address immediately after the destination address:
51 /// <https://www.rfc-editor.org/rfc/rfc894>.
52 #[inline]
53 pub fn source(&self) -> MacAddress {
54 MacAddress::new(self.bytes[SOURCE].try_into().expect("validated header"))
55 }
56
57 /// Returns the Ethernet protocol type.
58 ///
59 /// RFC 894 places the two-octet protocol type after the source address and transmits
60 /// it most-significant octet first: <https://www.rfc-editor.org/rfc/rfc894>.
61 #[inline]
62 pub fn ether_type(&self) -> EtherType {
63 EtherType::new(u16::from_be_bytes(
64 self.bytes[ETHER_TYPE].try_into().expect("validated header"),
65 ))
66 }
67
68 /// Returns the payload bytes following the fixed Ethernet II header.
69 ///
70 /// This is the data field after the type field in the RFC 894 Ethernet encapsulation:
71 /// <https://www.rfc-editor.org/rfc/rfc894>. The returned slice borrows the input.
72 #[inline]
73 pub fn payload(&self) -> &'a [u8] {
74 &self.bytes[HEADER_LENGTH..]
75 }
76
77 /// Returns all represented frame bytes.
78 ///
79 /// The byte layout is the destination/source/type/payload order described by
80 /// [RFC 894](https://www.rfc-editor.org/rfc/rfc894). Callers must remove any frame
81 /// check sequence (FCS) before parsing; it cannot be distinguished from payload here.
82 #[inline]
83 pub fn as_bytes(&self) -> &'a [u8] {
84 self.bytes
85 }
86}
87
88/// A validated mutable borrow of one Ethernet II frame.
89///
90/// Its fixed header uses the destination, source, and protocol-type order described by
91/// [RFC 894](https://www.rfc-editor.org/rfc/rfc894). Callers must remove any frame check
92/// sequence (FCS) before parsing because every supplied byte after the fixed header is
93/// payload.
94#[derive(Debug, Eq, PartialEq)]
95pub struct EthernetFrameMut<'a> {
96 bytes: &'a mut [u8],
97}
98
99impl<'a> EthernetFrameMut<'a> {
100 pub(super) fn from_validated(bytes: &'a mut [u8]) -> Self {
101 Self { bytes }
102 }
103
104 /// Validates and mutably borrows an Ethernet II frame.
105 ///
106 /// The parser rejects inputs shorter than the 14-octet destination/source/type
107 /// header described by [RFC 894](https://www.rfc-editor.org/rfc/rfc894). Every
108 /// remaining supplied octet is payload and remains available for independent protocol
109 /// parsing; callers must remove any frame check sequence (FCS) before parsing.
110 pub fn parse(bytes: &'a mut [u8]) -> Result<Self, ParseError> {
111 validate_frame_length(bytes.len())?;
112 Ok(Self { bytes })
113 }
114
115 /// Returns the destination Ethernet address.
116 ///
117 /// RFC 894 assigns the first six header octets to the destination address:
118 /// <https://www.rfc-editor.org/rfc/rfc894>.
119 #[inline]
120 pub fn destination(&self) -> MacAddress {
121 MacAddress::new(
122 self.bytes[DESTINATION]
123 .try_into()
124 .expect("validated header"),
125 )
126 }
127
128 /// Returns the source Ethernet address.
129 ///
130 /// RFC 894 assigns the next six header octets to the source address:
131 /// <https://www.rfc-editor.org/rfc/rfc894>.
132 #[inline]
133 pub fn source(&self) -> MacAddress {
134 MacAddress::new(self.bytes[SOURCE].try_into().expect("validated header"))
135 }
136
137 /// Returns the Ethernet protocol type.
138 ///
139 /// RFC 894 places this two-octet, most-significant-octet-first field after the source
140 /// address: <https://www.rfc-editor.org/rfc/rfc894>.
141 #[inline]
142 pub fn ether_type(&self) -> EtherType {
143 EtherType::new(u16::from_be_bytes(
144 self.bytes[ETHER_TYPE].try_into().expect("validated header"),
145 ))
146 }
147
148 /// Replaces the destination Ethernet address.
149 ///
150 /// This writes the first six header octets assigned to the destination address by
151 /// [RFC 894](https://www.rfc-editor.org/rfc/rfc894).
152 #[inline]
153 pub fn set_destination(&mut self, address: MacAddress) {
154 self.bytes[DESTINATION].copy_from_slice(&address.octets());
155 }
156
157 /// Replaces the source Ethernet address.
158 ///
159 /// This writes the six header octets assigned to the source address by
160 /// [RFC 894](https://www.rfc-editor.org/rfc/rfc894).
161 #[inline]
162 pub fn set_source(&mut self, address: MacAddress) {
163 self.bytes[SOURCE].copy_from_slice(&address.octets());
164 }
165
166 /// Replaces the Ethernet protocol type.
167 ///
168 /// This writes the most-significant-octet-first type field specified by
169 /// [RFC 894](https://www.rfc-editor.org/rfc/rfc894).
170 #[inline]
171 pub fn set_ether_type(&mut self, ether_type: EtherType) {
172 self.bytes[ETHER_TYPE].copy_from_slice(ðer_type.raw().to_be_bytes());
173 }
174
175 /// Returns the payload bytes following the fixed Ethernet II header.
176 ///
177 /// This borrows the data field after the type field in RFC 894's encapsulation:
178 /// <https://www.rfc-editor.org/rfc/rfc894>.
179 #[inline]
180 pub fn payload(&self) -> &[u8] {
181 &self.bytes[HEADER_LENGTH..]
182 }
183
184 /// Returns mutable payload bytes following the fixed Ethernet II header.
185 ///
186 /// This mutably borrows the data field after the type field in RFC 894's
187 /// encapsulation: <https://www.rfc-editor.org/rfc/rfc894>.
188 #[inline]
189 pub fn payload_mut(&mut self) -> &mut [u8] {
190 &mut self.bytes[HEADER_LENGTH..]
191 }
192
193 /// Returns all represented frame bytes.
194 ///
195 /// The represented order is destination, source, type, then payload as described by
196 /// [RFC 894](https://www.rfc-editor.org/rfc/rfc894).
197 #[inline]
198 pub fn as_bytes(&self) -> &[u8] {
199 self.bytes
200 }
201
202 /// Returns all represented mutable frame bytes.
203 ///
204 /// The represented order is destination, source, type, then payload as described by
205 /// [RFC 894](https://www.rfc-editor.org/rfc/rfc894).
206 #[inline]
207 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
208 self.bytes
209 }
210}
211
212fn validate_frame_length(available: usize) -> Result<(), ParseError> {
213 if available < HEADER_LENGTH {
214 return Err(ParseError::Truncated {
215 minimum: HEADER_LENGTH,
216 available,
217 });
218 }
219 Ok(())
220}