1 use crate::{err::Layer, err::SliceWriteSpaceError, *};
2 
3 /// Ethernet II header.
4 #[derive(Clone, Debug, Eq, PartialEq, Default)]
5 pub struct Ethernet2Header {
6     /// Source MAC Address
7     pub source: [u8; 6],
8     /// Destination MAC Address
9     pub destination: [u8; 6],
10     /// Protocol present after the ethernet2 header.
11     pub ether_type: EtherType,
12 }
13 
14 impl Ethernet2Header {
15     /// Serialized size of an Ethernet2 header in bytes/octets.
16     pub const LEN: usize = 14;
17 
18     /// Deprecated use [`Ethernet2Header::LEN`] instead.
19     #[deprecated(since = "0.14.0", note = "Use `Ethernet2Header::LEN` instead")]
20     pub const SERIALIZED_SIZE: usize = Ethernet2Header::LEN;
21 
22     /// Deprecated use [`Ethernet2Header::from_slice`] instead.
23     #[deprecated(since = "0.10.1", note = "Use Ethernet2Header::from_slice instead.")]
24     #[inline]
read_from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), err::LenError>25     pub fn read_from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), err::LenError> {
26         Ethernet2Header::from_slice(slice)
27     }
28 
29     /// Read an Ethernet2Header from a slice and return the header & unused parts of the slice.
30     #[inline]
from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), err::LenError>31     pub fn from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), err::LenError> {
32         Ok((
33             Ethernet2HeaderSlice::from_slice(slice)?.to_header(),
34             &slice[Ethernet2Header::LEN..],
35         ))
36     }
37 
38     /// Read an Ethernet2Header from a static sized byte array.
39     #[inline]
from_bytes(bytes: [u8; 14]) -> Ethernet2Header40     pub fn from_bytes(bytes: [u8; 14]) -> Ethernet2Header {
41         Ethernet2Header {
42             destination: [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]],
43             source: [bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11]],
44             ether_type: EtherType(u16::from_be_bytes([bytes[12], bytes[13]])),
45         }
46     }
47 
48     /// Reads an Ethernet-II header from the current position of the read argument.
49     #[cfg(feature = "std")]
50     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
read<T: std::io::Read + std::io::Seek + Sized>( reader: &mut T, ) -> Result<Ethernet2Header, std::io::Error>51     pub fn read<T: std::io::Read + std::io::Seek + Sized>(
52         reader: &mut T,
53     ) -> Result<Ethernet2Header, std::io::Error> {
54         let buffer = {
55             let mut buffer = [0; Ethernet2Header::LEN];
56             reader.read_exact(&mut buffer)?;
57             buffer
58         };
59 
60         Ok(
61             // SAFETY: Safe as the buffer contains exactly the needed Ethernet2Header::LEN bytes.
62             unsafe { Ethernet2HeaderSlice::from_slice_unchecked(&buffer) }.to_header(),
63         )
64     }
65 
66     /// Serialize the header to a given slice. Returns the unused part of the slice.
write_to_slice<'a>( &self, slice: &'a mut [u8], ) -> Result<&'a mut [u8], SliceWriteSpaceError>67     pub fn write_to_slice<'a>(
68         &self,
69         slice: &'a mut [u8],
70     ) -> Result<&'a mut [u8], SliceWriteSpaceError> {
71         // length check
72         if slice.len() < Ethernet2Header::LEN {
73             Err(SliceWriteSpaceError {
74                 required_len: Ethernet2Header::LEN,
75                 len: slice.len(),
76                 layer: Layer::Ethernet2Header,
77                 layer_start_offset: 0,
78             })
79         } else {
80             slice[..Ethernet2Header::LEN].copy_from_slice(&self.to_bytes());
81             Ok(&mut slice[Ethernet2Header::LEN..])
82         }
83     }
84 
85     /// Writes a given Ethernet-II header to the current position of the write argument.
86     #[cfg(feature = "std")]
87     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
88     #[inline]
write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error>89     pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
90         writer.write_all(&self.to_bytes())
91     }
92 
93     /// Length of the serialized header in bytes.
94     #[inline]
header_len(&self) -> usize95     pub fn header_len(&self) -> usize {
96         14
97     }
98 
99     /// Returns the serialized form of the header as a statically
100     /// sized byte array.
101     #[inline]
to_bytes(&self) -> [u8; 14]102     pub fn to_bytes(&self) -> [u8; 14] {
103         let ether_type_be = self.ether_type.0.to_be_bytes();
104         [
105             self.destination[0],
106             self.destination[1],
107             self.destination[2],
108             self.destination[3],
109             self.destination[4],
110             self.destination[5],
111             self.source[0],
112             self.source[1],
113             self.source[2],
114             self.source[3],
115             self.source[4],
116             self.source[5],
117             ether_type_be[0],
118             ether_type_be[1],
119         ]
120     }
121 }
122 
123 #[cfg(test)]
124 mod test {
125     use super::*;
126     use crate::test_gens::*;
127     use alloc::{format, vec::Vec};
128     use proptest::prelude::*;
129     use std::io::{Cursor, ErrorKind};
130 
131     #[test]
default()132     fn default() {
133         let e: Ethernet2Header = Default::default();
134         assert_eq!([0u8; 6], e.source);
135         assert_eq!([0u8; 6], e.destination);
136         assert_eq!(EtherType(0), e.ether_type);
137     }
138 
139     proptest! {
140         #[test]
141         fn from_slice(
142             input in ethernet_2_any(),
143             dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
144         ) {
145             // serialize
146             let mut buffer: Vec<u8> = Vec::with_capacity(14 + dummy_data.len());
147             input.write(&mut buffer).unwrap();
148             buffer.extend(&dummy_data[..]);
149 
150             // calls with a valid result
151             {
152                 let (result, rest) = Ethernet2Header::from_slice(&buffer[..]).unwrap();
153                 assert_eq!(input, result);
154                 assert_eq!(&buffer[14..], rest);
155             }
156             #[allow(deprecated)]
157             {
158                 let (result, rest) = Ethernet2Header::read_from_slice(&buffer[..]).unwrap();
159                 assert_eq!(input, result);
160                 assert_eq!(&buffer[14..], rest);
161             }
162 
163             // call with not enough data in the slice
164             for len in 0..=13 {
165                 assert_eq!(
166                     Ethernet2Header::from_slice(&buffer[..len]),
167                     Err(err::LenError{
168                         required_len: Ethernet2Header::LEN,
169                         len: len,
170                         len_source: LenSource::Slice,
171                         layer: err::Layer::Ethernet2Header,
172                         layer_start_offset: 0,
173                     })
174                 );
175             }
176         }
177     }
178 
179     proptest! {
180         #[test]
181         fn from_bytes(input in ethernet_2_any()) {
182             assert_eq!(
183                 input,
184                 Ethernet2Header::from_bytes(input.to_bytes())
185             );
186         }
187     }
188 
189     proptest! {
190         #[test]
191         fn read(
192             input in ethernet_2_any(),
193             dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
194         ) {
195             // normal read
196             let mut buffer = Vec::with_capacity(14 + dummy_data.len());
197             input.write(&mut buffer).unwrap();
198             buffer.extend(&dummy_data[..]);
199 
200             // calls with a valid result
201             {
202                 let mut cursor = Cursor::new(&buffer);
203                 let result = Ethernet2Header::read(&mut cursor).unwrap();
204                 assert_eq!(input, result);
205                 assert_eq!(cursor.position(), 14);
206             }
207 
208             // unexpected eof
209             for len in 0..=13 {
210                 let mut cursor = Cursor::new(&buffer[0..len]);
211                 assert_eq!(
212                     Ethernet2Header::read(&mut cursor)
213                     .unwrap_err()
214                     .kind(),
215                     ErrorKind::UnexpectedEof
216                 );
217             }
218         }
219     }
220 
221     proptest! {
222         #[test]
223         fn write_to_slice(input in ethernet_2_any()) {
224             // normal write
225             {
226                 let mut buffer: [u8;14] = [0;14];
227                 input.write_to_slice(&mut buffer).unwrap();
228                 assert_eq!(buffer, input.to_bytes());
229             }
230             // len to small
231             for len in 0..14 {
232                 let mut buffer: [u8;14] = [0;14];
233                 assert_eq!(
234                     SliceWriteSpaceError {
235                         required_len: Ethernet2Header::LEN,
236                         len,
237                         layer: Layer::Ethernet2Header,
238                         layer_start_offset: 0,
239                     },
240                     input.write_to_slice(&mut buffer[..len]).unwrap_err()
241                 );
242             }
243         }
244     }
245 
246     proptest! {
247         #[test]
248         fn write(input in ethernet_2_any()) {
249             // successful write
250             {
251                 let mut buffer: Vec<u8> = Vec::with_capacity(14);
252                 input.write(&mut buffer).unwrap();
253                 assert_eq!(&buffer[..], &input.to_bytes());
254             }
255 
256             // not enough memory for write (unexpected eof)
257             for len in 0..8 {
258                 let mut buffer = [0u8;8];
259                 let mut writer = Cursor::new(&mut buffer[..len]);
260                 assert!(input.write(&mut writer).is_err());
261             }
262         }
263     }
264 
265     proptest! {
266         #[test]
267         fn header_len(input in ethernet_2_any()) {
268             assert_eq!(input.header_len(), 14);
269         }
270     }
271 
272     proptest! {
273         #[test]
274         fn to_bytes(input in ethernet_2_any()) {
275             let ether_type_be = input.ether_type.0.to_be_bytes();
276             assert_eq!(
277                 input.to_bytes(),
278                 [
279                     input.destination[0],
280                     input.destination[1],
281                     input.destination[2],
282                     input.destination[3],
283                     input.destination[4],
284                     input.destination[5],
285                     input.source[0],
286                     input.source[1],
287                     input.source[2],
288                     input.source[3],
289                     input.source[4],
290                     input.source[5],
291                     ether_type_be[0],
292                     ether_type_be[1],
293                 ]
294             );
295         }
296     }
297 
298     proptest! {
299         #[test]
300         fn clone_eq(input in ethernet_2_any()) {
301             assert_eq!(input, input.clone());
302         }
303     }
304 
305     proptest! {
306         #[test]
307         fn dbg(input in ethernet_2_any()) {
308             assert_eq!(
309                 &format!(
310                     "Ethernet2Header {{ source: {:?}, destination: {:?}, ether_type: {:?} }}",
311                     input.source,
312                     input.destination,
313                     input.ether_type
314                 ),
315                 &format!("{:?}", input)
316             );
317         }
318     }
319 }
320