1 use crate::*; 2 3 /// IEEE 802.1Q double VLAN Tagging Header 4 #[derive(Clone, Debug, Eq, PartialEq)] 5 pub struct DoubleVlanHeader { 6 /// The outer vlan tagging header 7 pub outer: SingleVlanHeader, 8 /// The inner vlan tagging header 9 pub inner: SingleVlanHeader, 10 } 11 12 impl DoubleVlanHeader { 13 /// Serialized size of two VLAN headers in bytes/octets. 14 pub const LEN: usize = 8; 15 16 #[deprecated(since = "0.14.0", note = "Use `DoubleVlanHeader::LEN` instead")] 17 pub const SERIALIZED_SIZE: usize = DoubleVlanHeader::LEN; 18 19 /// Read an DoubleVlanHeader from a slice and return the header & unused parts of the slice. 20 #[deprecated(since = "0.10.1", note = "Use SingleVlanHeader::from_slice instead.")] 21 #[inline] read_from_slice( slice: &[u8], ) -> Result<(DoubleVlanHeader, &[u8]), err::double_vlan::HeaderSliceError>22 pub fn read_from_slice( 23 slice: &[u8], 24 ) -> Result<(DoubleVlanHeader, &[u8]), err::double_vlan::HeaderSliceError> { 25 DoubleVlanHeader::from_slice(slice) 26 } 27 28 /// Read an DoubleVlanHeader from a slice and return the header & unused parts of the slice. 29 #[inline] from_slice( slice: &[u8], ) -> Result<(DoubleVlanHeader, &[u8]), err::double_vlan::HeaderSliceError>30 pub fn from_slice( 31 slice: &[u8], 32 ) -> Result<(DoubleVlanHeader, &[u8]), err::double_vlan::HeaderSliceError> { 33 Ok(( 34 DoubleVlanHeaderSlice::from_slice(slice)?.to_header(), 35 &slice[DoubleVlanHeader::LEN..], 36 )) 37 } 38 39 /// Read a double tagging header from the given source 40 #[cfg(feature = "std")] 41 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] read<T: std::io::Read + std::io::Seek + Sized>( reader: &mut T, ) -> Result<DoubleVlanHeader, err::double_vlan::HeaderReadError>42 pub fn read<T: std::io::Read + std::io::Seek + Sized>( 43 reader: &mut T, 44 ) -> Result<DoubleVlanHeader, err::double_vlan::HeaderReadError> { 45 use err::double_vlan::{HeaderError::*, HeaderReadError::*}; 46 47 let outer = SingleVlanHeader::read(reader).map_err(Io)?; 48 49 use crate::ether_type::{PROVIDER_BRIDGING, VLAN_DOUBLE_TAGGED_FRAME, VLAN_TAGGED_FRAME}; 50 //check that outer ethertype is matching 51 match outer.ether_type { 52 VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => { 53 Ok(DoubleVlanHeader { 54 outer, 55 inner: SingleVlanHeader::read(reader).map_err(Io)?, 56 }) 57 } 58 value => Err(Content(NonVlanEtherType { 59 unexpected_ether_type: value, 60 })), 61 } 62 } 63 64 /// Write the double IEEE 802.1Q VLAN tagging header 65 #[cfg(feature = "std")] 66 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error>67 pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> { 68 self.outer.write(writer)?; 69 self.inner.write(writer) 70 } 71 72 /// Length of the serialized headers in bytes. 73 #[inline] header_len(&self) -> usize74 pub fn header_len(&self) -> usize { 75 8 76 } 77 78 /// Returns the serialized form of the headers or an value error in case 79 /// the headers contain values that are outside of range. 80 #[inline] to_bytes(&self) -> [u8; 8]81 pub fn to_bytes(&self) -> [u8; 8] { 82 let outer = self.outer.to_bytes(); 83 let inner = self.inner.to_bytes(); 84 [ 85 outer[0], outer[1], outer[2], outer[3], inner[0], inner[1], inner[2], inner[3], 86 ] 87 } 88 } 89 90 impl Default for DoubleVlanHeader { default() -> Self91 fn default() -> Self { 92 DoubleVlanHeader { 93 outer: SingleVlanHeader { 94 pcp: VlanPcp::ZERO, 95 drop_eligible_indicator: false, 96 vlan_id: Default::default(), 97 ether_type: ether_type::VLAN_TAGGED_FRAME, 98 }, 99 inner: Default::default(), 100 } 101 } 102 } 103 104 #[cfg(test)] 105 mod test { 106 use crate::{test_gens::*, *}; 107 use alloc::{format, vec::Vec}; 108 use proptest::prelude::*; 109 use std::io::{Cursor, ErrorKind}; 110 111 #[test] constants()112 fn constants() { 113 assert_eq!(8, DoubleVlanHeader::LEN); 114 } 115 116 proptest! { 117 #[test] 118 fn from_slice( 119 input in vlan_double_any(), 120 dummy_data in proptest::collection::vec(any::<u8>(), 0..20), 121 ether_type_non_vlan in ether_type_any().prop_filter( 122 "ether_type must not be a vlan ether type", 123 |v| !VlanHeader::VLAN_ETHER_TYPES.iter().any(|&x| v == &x) 124 ) 125 ) { 126 use err::double_vlan::{HeaderError::*, HeaderSliceError::*}; 127 128 // serialize 129 let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len() + dummy_data.len()); 130 input.write(&mut buffer).unwrap(); 131 buffer.extend(&dummy_data[..]); 132 133 // normal 134 { 135 let (result, rest) = DoubleVlanHeader::from_slice(&buffer).unwrap(); 136 assert_eq!(result, input); 137 assert_eq!(rest, &buffer[8..]); 138 } 139 #[allow(deprecated)] 140 { 141 let (result, rest) = DoubleVlanHeader::read_from_slice(&buffer).unwrap(); 142 assert_eq!(result, input); 143 assert_eq!(rest, &buffer[8..]); 144 } 145 146 // slice length to small 147 for len in 0..8 { 148 assert_eq!( 149 DoubleVlanHeader::from_slice(&buffer[..len]) 150 .unwrap_err(), 151 Len(err::LenError{ 152 required_len: 8, 153 len: len, 154 len_source: LenSource::Slice, 155 layer: err::Layer::VlanHeader, 156 layer_start_offset: 0, 157 }) 158 ); 159 } 160 161 // bad outer ether type 162 { 163 let mut bad_outer = input.clone(); 164 bad_outer.outer.ether_type = ether_type_non_vlan; 165 let bytes = bad_outer.to_bytes(); 166 assert_eq!( 167 DoubleVlanHeader::from_slice(&bytes) 168 .unwrap_err(), 169 Content(NonVlanEtherType{ 170 unexpected_ether_type: ether_type_non_vlan, 171 }) 172 ); 173 } 174 } 175 } 176 177 proptest! { 178 #[test] 179 fn read( 180 input in vlan_double_any(), 181 dummy_data in proptest::collection::vec(any::<u8>(), 0..20), 182 ether_type_non_vlan in ether_type_any().prop_filter( 183 "ether_type must not be a vlan ether type", 184 |v| !VlanHeader::VLAN_ETHER_TYPES.iter().any(|&x| v == &x) 185 ) 186 ) { 187 use err::double_vlan::HeaderError::*; 188 189 // serialize 190 let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len() + dummy_data.len()); 191 input.write(&mut buffer).unwrap(); 192 buffer.extend(&dummy_data[..]); 193 194 // normal 195 { 196 let mut cursor = Cursor::new(&buffer); 197 let result = DoubleVlanHeader::read(&mut cursor).unwrap(); 198 assert_eq!(result, input); 199 assert_eq!(8, cursor.position()); 200 } 201 202 // outer & inner error 203 for len in 0..8 { 204 let mut cursor = Cursor::new(&buffer[0..len]); 205 assert_eq!( 206 DoubleVlanHeader::read(&mut cursor) 207 .unwrap_err() 208 .io_error() 209 .unwrap() 210 .kind(), 211 ErrorKind::UnexpectedEof 212 ); 213 } 214 215 // bad outer ether type 216 { 217 let mut bad_outer = input.clone(); 218 bad_outer.outer.ether_type = ether_type_non_vlan; 219 let bytes = bad_outer.to_bytes(); 220 let mut cursor = Cursor::new(&bytes); 221 assert_eq!( 222 DoubleVlanHeader::read(&mut cursor) 223 .unwrap_err() 224 .content_error() 225 .unwrap(), 226 NonVlanEtherType{ 227 unexpected_ether_type: ether_type_non_vlan, 228 } 229 ); 230 } 231 } 232 } 233 234 proptest! { 235 #[test] 236 fn write_and_to_bytes(input in vlan_double_any()) { 237 // normal write 238 { 239 let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len()); 240 input.write(&mut buffer).unwrap(); 241 assert_eq!(&buffer[..], &input.to_bytes()); 242 { 243 let inner_bytes = input.inner.to_bytes(); 244 let outer_bytes = input.outer.to_bytes(); 245 assert_eq!( 246 input.to_bytes(), 247 [ 248 outer_bytes[0], 249 outer_bytes[1], 250 outer_bytes[2], 251 outer_bytes[3], 252 inner_bytes[0], 253 inner_bytes[1], 254 inner_bytes[2], 255 inner_bytes[3], 256 ] 257 ); 258 } 259 } 260 261 // io error 262 for len in 0..DoubleVlanHeader::LEN { 263 let mut buf = [0u8;DoubleVlanHeader::LEN]; 264 let mut cursor = Cursor::new(&mut buf[..len]); 265 assert!(input.write(&mut cursor).is_err()); 266 } 267 } 268 } 269 270 proptest! { 271 #[test] 272 fn header_len(input in vlan_double_any()) { 273 assert_eq!(8, input.header_len()); 274 } 275 } 276 277 #[test] default()278 fn default() { 279 let actual: DoubleVlanHeader = Default::default(); 280 assert_eq!(actual.outer, { 281 let mut outer: SingleVlanHeader = Default::default(); 282 outer.ether_type = ether_type::VLAN_TAGGED_FRAME; 283 outer 284 }); 285 assert_eq!(actual.inner, Default::default()); 286 } 287 288 proptest! { 289 #[test] 290 fn clone_eq(input in vlan_double_any()) { 291 assert_eq!(input, input.clone()); 292 } 293 } 294 295 proptest! { 296 #[test] 297 fn dbg(input in vlan_double_any()) { 298 assert_eq!( 299 &format!( 300 "DoubleVlanHeader {{ outer: {:?}, inner: {:?} }}", 301 input.outer, 302 input.inner, 303 ), 304 &format!("{:?}", input) 305 ); 306 } 307 } 308 } 309