1 use crate::*; 2 use core::slice::from_raw_parts; 3 4 /// A slice containing an double vlan header of a network package. 5 #[derive(Clone, Debug, Eq, PartialEq)] 6 pub struct DoubleVlanHeaderSlice<'a> { 7 pub(crate) slice: &'a [u8], 8 } 9 10 impl<'a> DoubleVlanHeaderSlice<'a> { 11 /// Creates a double header slice from a slice. from_slice( slice: &'a [u8], ) -> Result<DoubleVlanHeaderSlice<'a>, err::double_vlan::HeaderSliceError>12 pub fn from_slice( 13 slice: &'a [u8], 14 ) -> Result<DoubleVlanHeaderSlice<'a>, err::double_vlan::HeaderSliceError> { 15 use err::double_vlan::{HeaderError::*, HeaderSliceError::*}; 16 17 // check length 18 if slice.len() < DoubleVlanHeader::LEN { 19 return Err(Len(err::LenError { 20 required_len: DoubleVlanHeader::LEN, 21 len: slice.len(), 22 len_source: LenSource::Slice, 23 layer: err::Layer::VlanHeader, 24 layer_start_offset: 0, 25 })); 26 } 27 28 // create slice 29 let result = DoubleVlanHeaderSlice { 30 // SAFETY: 31 // Safe as the slice length is checked is before to have 32 // at least the length of DoubleVlanHeader::LEN (8) 33 slice: unsafe { from_raw_parts(slice.as_ptr(), DoubleVlanHeader::LEN) }, 34 }; 35 36 use ether_type::*; 37 38 //check that outer ethertype is matching 39 match result.outer().ether_type() { 40 VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => { 41 //all done 42 Ok(result) 43 } 44 value => Err(Content(NonVlanEtherType { 45 unexpected_ether_type: value, 46 })), 47 } 48 } 49 50 /// Returns the slice containing the double vlan header 51 #[inline] slice(&self) -> &'a [u8]52 pub fn slice(&self) -> &'a [u8] { 53 self.slice 54 } 55 56 /// Returns a slice with the outer vlan header 57 #[inline] outer(&self) -> SingleVlanHeaderSlice<'a>58 pub fn outer(&self) -> SingleVlanHeaderSlice<'a> { 59 // SAFETY: 60 // Safe as the constructor checks that the slice has the length 61 // of DoubleVlanHeader::LEN (8) and the 62 // SingleVlanHeader::LEN has a size of 4. 63 unsafe { 64 SingleVlanHeaderSlice::from_slice_unchecked(from_raw_parts( 65 self.slice.as_ptr(), 66 SingleVlanHeader::LEN, 67 )) 68 } 69 } 70 71 /// Returns a slice with the inner vlan header. 72 #[inline] inner(&self) -> SingleVlanHeaderSlice<'a>73 pub fn inner(&self) -> SingleVlanHeaderSlice<'a> { 74 // SAFETY: 75 // Safe as the constructor checks that the slice has the length 76 // of DoubleVlanHeader::LEN (8) and the 77 // SingleVlanHeader::LEN has a size of 4. 78 unsafe { 79 SingleVlanHeaderSlice::from_slice_unchecked(from_raw_parts( 80 self.slice.as_ptr().add(SingleVlanHeader::LEN), 81 SingleVlanHeader::LEN, 82 )) 83 } 84 } 85 86 /// Decode all the fields and copy the results to a DoubleVlanHeader struct to_header(&self) -> DoubleVlanHeader87 pub fn to_header(&self) -> DoubleVlanHeader { 88 DoubleVlanHeader { 89 outer: self.outer().to_header(), 90 inner: self.inner().to_header(), 91 } 92 } 93 } 94 95 #[cfg(test)] 96 mod test { 97 use crate::{test_gens::*, *}; 98 use alloc::{format, vec::Vec}; 99 use proptest::prelude::*; 100 101 proptest! { 102 #[test] 103 fn from_slice( 104 input in vlan_double_any(), 105 dummy_data in proptest::collection::vec(any::<u8>(), 0..20), 106 ether_type_non_vlan in ether_type_any().prop_filter( 107 "ether_type must not be a vlan ether type", 108 |v| !VlanHeader::VLAN_ETHER_TYPES.iter().any(|&x| v == &x) 109 ) 110 ) { 111 use err::double_vlan::{HeaderError::*, HeaderSliceError::*}; 112 { 113 // serialize 114 let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len() + dummy_data.len()); 115 input.write(&mut buffer).unwrap(); 116 buffer.extend(&dummy_data[..]); 117 118 // normal 119 { 120 let slice = DoubleVlanHeaderSlice::from_slice(&buffer).unwrap(); 121 assert_eq!(slice.slice(), &buffer[..8]); 122 } 123 124 // slice length to small 125 for len in 0..8 { 126 assert_eq!( 127 DoubleVlanHeaderSlice::from_slice(&buffer[..len]) 128 .unwrap_err(), 129 130 Len(err::LenError{ 131 required_len: 8, 132 len: len, 133 len_source: LenSource::Slice, 134 layer: err::Layer::VlanHeader, 135 layer_start_offset: 0, 136 }) 137 ); 138 } 139 } 140 141 // bad outer ether type 142 { 143 let mut bad_outer = input.clone(); 144 bad_outer.outer.ether_type = ether_type_non_vlan; 145 assert_eq!( 146 DoubleVlanHeaderSlice::from_slice(&bad_outer.to_bytes()) 147 .unwrap_err(), 148 Content(NonVlanEtherType{ unexpected_ether_type: ether_type_non_vlan }) 149 ); 150 } 151 } 152 } 153 154 proptest! { 155 #[test] 156 fn getters(input in vlan_double_any()) { 157 let bytes = input.to_bytes(); 158 let slice = DoubleVlanHeaderSlice::from_slice(&bytes).unwrap(); 159 160 assert_eq!(input.outer, slice.outer().to_header()); 161 assert_eq!(input.inner, slice.inner().to_header()); 162 } 163 } 164 165 proptest! { 166 #[test] 167 fn to_header(input in vlan_double_any()) { 168 let bytes = input.to_bytes(); 169 let slice = DoubleVlanHeaderSlice::from_slice(&bytes).unwrap(); 170 171 assert_eq!( 172 DoubleVlanHeader{ 173 outer: input.outer, 174 inner: input.inner, 175 }, 176 slice.to_header() 177 ); 178 } 179 } 180 181 proptest! { 182 #[test] 183 fn clone_eq(input in vlan_double_any()) { 184 let bytes = input.to_bytes(); 185 let slice = DoubleVlanHeaderSlice::from_slice(&bytes).unwrap(); 186 assert_eq!(slice, slice.clone()); 187 } 188 } 189 190 proptest! { 191 #[test] 192 fn dbg(input in vlan_double_any()) { 193 let bytes = input.to_bytes(); 194 let slice = DoubleVlanHeaderSlice::from_slice(&bytes).unwrap(); 195 assert_eq!( 196 &format!( 197 "DoubleVlanHeaderSlice {{ slice: {:?} }}", 198 slice.slice(), 199 ), 200 &format!("{:?}", slice) 201 ); 202 } 203 } 204 } 205