1 use crate::*; 2 use core::slice::from_raw_parts; 3 4 ///A slice containing an ethernet 2 header of a network package. 5 #[derive(Clone, Debug, Eq, PartialEq)] 6 pub struct Ethernet2HeaderSlice<'a> { 7 pub(crate) slice: &'a [u8], 8 } 9 10 impl<'a> Ethernet2HeaderSlice<'a> { 11 /// Creates a ethernet slice from an other slice. from_slice(slice: &'a [u8]) -> Result<Ethernet2HeaderSlice<'a>, err::LenError>12 pub fn from_slice(slice: &'a [u8]) -> Result<Ethernet2HeaderSlice<'a>, err::LenError> { 13 //check length 14 if slice.len() < Ethernet2Header::LEN { 15 return Err(err::LenError { 16 required_len: Ethernet2Header::LEN, 17 len: slice.len(), 18 len_source: LenSource::Slice, 19 layer: err::Layer::Ethernet2Header, 20 layer_start_offset: 0, 21 }); 22 } 23 24 //all done 25 Ok(Ethernet2HeaderSlice { 26 // SAFETY: 27 // Safe as slice length is checked to be at least 28 // Ethernet2Header::LEN (14) before this. 29 slice: unsafe { from_raw_parts(slice.as_ptr(), Ethernet2Header::LEN) }, 30 }) 31 } 32 33 /// Converts the given slice into a ethernet 2 header slice WITHOUT any 34 /// checks to ensure that the data present is an ethernet 2 header or that the 35 /// slice length is matching the header length. 36 /// 37 /// If you are not sure what this means, use [`Ethernet2HeaderSlice::from_slice`] 38 /// instead. 39 /// 40 /// # Safety 41 /// 42 /// The caller must ensured that the given slice has the length of 43 /// [`Ethernet2Header::LEN`] 44 #[inline] 45 #[cfg(feature = "std")] from_slice_unchecked(slice: &[u8]) -> Ethernet2HeaderSlice46 pub(crate) unsafe fn from_slice_unchecked(slice: &[u8]) -> Ethernet2HeaderSlice { 47 debug_assert!(slice.len() == Ethernet2Header::LEN); 48 Ethernet2HeaderSlice { slice } 49 } 50 51 /// Returns the slice containing the ethernet 2 header 52 #[inline] slice(&self) -> &'a [u8]53 pub fn slice(&self) -> &'a [u8] { 54 self.slice 55 } 56 57 /// Read the destination MAC address 58 #[inline] destination(&self) -> [u8; 6]59 pub fn destination(&self) -> [u8; 6] { 60 // SAFETY: 61 // Safe as the contructor checks that the slice has 62 // at least the length of Ethernet2Header::LEN (14). 63 unsafe { get_unchecked_6_byte_array(self.slice.as_ptr()) } 64 } 65 66 /// Read the source MAC address 67 #[inline] source(&self) -> [u8; 6]68 pub fn source(&self) -> [u8; 6] { 69 // SAFETY: 70 // Safe as the contructor checks that the slice has 71 // at least the length of Ethernet2Header::LEN (14). 72 unsafe { get_unchecked_6_byte_array(self.slice.as_ptr().add(6)) } 73 } 74 75 /// Read the ether_type field of the header indicating the protocol 76 /// after the header. 77 #[inline] ether_type(&self) -> EtherType78 pub fn ether_type(&self) -> EtherType { 79 // SAFETY: 80 // Safe as the contructor checks that the slice has 81 // at least the length of Ethernet2Header::LEN (14). 82 EtherType(unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(12)) }) 83 } 84 85 /// Decode all the fields and copy the results to a [`Ethernet2Header`] struct to_header(&self) -> Ethernet2Header86 pub fn to_header(&self) -> Ethernet2Header { 87 Ethernet2Header { 88 source: self.source(), 89 destination: self.destination(), 90 ether_type: self.ether_type(), 91 } 92 } 93 } 94 95 #[cfg(test)] 96 mod test { 97 use super::*; 98 use crate::test_gens::*; 99 use alloc::{format, vec::Vec}; 100 use proptest::prelude::*; 101 102 proptest! { 103 #[test] 104 fn from_slice( 105 input in ethernet_2_any(), 106 dummy_data in proptest::collection::vec(any::<u8>(), 0..20) 107 ) { 108 // serialize 109 let mut buffer: Vec<u8> = Vec::with_capacity(14 + dummy_data.len()); 110 input.write(&mut buffer).unwrap(); 111 buffer.extend(&dummy_data[..]); 112 113 // calls with a valid result 114 { 115 let result = Ethernet2HeaderSlice::from_slice(&buffer[..]).unwrap(); 116 assert_eq!(&buffer[..14], result.slice()); 117 } 118 119 // call with not enough data in the slice 120 for len in 0..=13 { 121 assert_eq!( 122 Ethernet2HeaderSlice::from_slice(&buffer[..len]), 123 Err(err::LenError{ 124 required_len: Ethernet2Header::LEN, 125 len: len, 126 len_source: LenSource::Slice, 127 layer: err::Layer::Ethernet2Header, 128 layer_start_offset: 0, 129 }) 130 ); 131 } 132 } 133 } 134 135 proptest! { 136 #[test] 137 fn getters(input in ethernet_2_any()) { 138 let buffer = input.to_bytes(); 139 let slice = Ethernet2HeaderSlice::from_slice(&buffer).unwrap(); 140 assert_eq!(input.destination, slice.destination()); 141 assert_eq!(input.source, slice.source()); 142 assert_eq!(input.ether_type, slice.ether_type()); 143 } 144 } 145 146 proptest! { 147 #[test] 148 fn to_header(input in ethernet_2_any()) { 149 let buffer = input.to_bytes(); 150 let slice = Ethernet2HeaderSlice::from_slice(&buffer).unwrap(); 151 assert_eq!(input, slice.to_header()); 152 } 153 } 154 155 proptest! { 156 #[test] 157 fn clone_eq(input in ethernet_2_any()) { 158 let buffer = input.to_bytes(); 159 let slice = Ethernet2HeaderSlice::from_slice(&buffer).unwrap(); 160 assert_eq!(slice, slice.clone()); 161 } 162 } 163 164 proptest! { 165 #[test] 166 fn dbg(input in ethernet_2_any()) { 167 let buffer = input.to_bytes(); 168 let slice = Ethernet2HeaderSlice::from_slice(&buffer).unwrap(); 169 assert_eq!( 170 &format!( 171 "Ethernet2HeaderSlice {{ slice: {:?} }}", 172 slice.slice() 173 ), 174 &format!("{:?}", slice) 175 ); 176 } 177 } 178 } 179