• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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