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