• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::{err::*, *};
2 
3 /// Slice containing a VLAN header & payload.
4 #[derive(Clone, Eq, PartialEq)]
5 pub struct DoubleVlanSlice<'a> {
6     pub(crate) slice: &'a [u8],
7 }
8 
9 impl<'a> DoubleVlanSlice<'a> {
10     /// Try creating a [`DoubleVlanSlice`] from a slice containing the
11     /// VLAN header & payload.
from_slice( slice: &'a [u8], ) -> Result<DoubleVlanSlice<'a>, err::double_vlan::HeaderSliceError>12     pub fn from_slice(
13         slice: &'a [u8],
14     ) -> Result<DoubleVlanSlice<'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(LenError {
20                 required_len: DoubleVlanHeader::LEN,
21                 len: slice.len(),
22                 len_source: LenSource::Slice,
23                 layer: Layer::VlanHeader,
24                 layer_start_offset: 0,
25             }));
26         }
27 
28         // create slice
29         let result = DoubleVlanSlice { slice };
30 
31         // check that outer ethertype is matching
32         use ether_type::*;
33         match result.outer().ether_type() {
34             VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => Ok(result),
35             value => Err(Content(NonVlanEtherType {
36                 unexpected_ether_type: value,
37             })),
38         }
39     }
40 
41     /// Returns the slice containing the VLAN header and payload.
42     #[inline]
slice(&self) -> &'a [u8]43     pub fn slice(&self) -> &'a [u8] {
44         self.slice
45     }
46 
47     /// Outer VLAN header & payload (includes header of inner vlan header).
48     #[inline]
outer(&self) -> SingleVlanSlice49     pub fn outer(&self) -> SingleVlanSlice {
50         SingleVlanSlice { slice: self.slice }
51     }
52 
53     /// Inner VLAN header & payload.
54     #[inline]
inner(&self) -> SingleVlanSlice55     pub fn inner(&self) -> SingleVlanSlice {
56         SingleVlanSlice {
57             slice: unsafe {
58                 // SAFETY: Safe as "from_slice" verified the slice length
59                 // to be DoubleVlanHeader::LEN (aka 2*SingleVlanHeader::LEN).
60                 core::slice::from_raw_parts(
61                     self.slice.as_ptr().add(SingleVlanHeader::LEN),
62                     self.slice.len() - SingleVlanHeader::LEN,
63                 )
64             },
65         }
66     }
67 
68     /// Decode all the fields and copy the results to a DoubleVlanHeader struct
69     #[inline]
to_header(&self) -> DoubleVlanHeader70     pub fn to_header(&self) -> DoubleVlanHeader {
71         DoubleVlanHeader {
72             outer: self.outer().to_header(),
73             inner: self.inner().to_header(),
74         }
75     }
76 
77     /// Returns the slice containing the payload & ether type
78     /// identifying it's content type after bother VLAN headers.
79     #[inline]
payload(&self) -> EtherPayloadSlice<'a>80     pub fn payload(&self) -> EtherPayloadSlice<'a> {
81         EtherPayloadSlice {
82             ether_type: self.inner().ether_type(),
83             payload: self.payload_slice(),
84         }
85     }
86 
87     /// Returns the slice containing the payload after both
88     /// VLAN headers.
payload_slice(&self) -> &'a [u8]89     pub fn payload_slice(&self) -> &'a [u8] {
90         unsafe {
91             // SAFETY:
92             // Safe as the contructor checks that the slice has
93             // at least the length of DoubleVlanHeader::LEN (8).
94             core::slice::from_raw_parts(
95                 self.slice.as_ptr().add(DoubleVlanHeader::LEN),
96                 self.slice.len() - DoubleVlanHeader::LEN,
97             )
98         }
99     }
100 
101     /// Length of the VLAN header in bytes (equal to
102     /// [`crate::DoubleVlanHeader::LEN`]).
103     #[inline]
header_len(&self) -> usize104     pub const fn header_len(&self) -> usize {
105         DoubleVlanHeader::LEN
106     }
107 }
108 
109 impl core::fmt::Debug for DoubleVlanSlice<'_> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result110     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111         f.debug_struct("DoubleVlanSlice")
112             .field("outer", &self.outer().to_header())
113             .field("inner", &self.inner().to_header())
114             .field("payload", &self.payload())
115             .finish()
116     }
117 }
118 
119 #[cfg(test)]
120 mod test {
121     use super::*;
122     use crate::test_gens::*;
123     use alloc::{format, vec::Vec};
124     use proptest::prelude::*;
125 
126     proptest! {
127         #[test]
128         fn debug_clone_eq(
129             vlan in vlan_double_any()
130         ) {
131             let payload: [u8;8] = [1,2,3,4,5,6,7,8];
132             let mut data = Vec::with_capacity(
133                 vlan.header_len() +
134                 payload.len()
135             );
136             data.extend_from_slice(&vlan.to_bytes());
137             data.extend_from_slice(&payload);
138 
139             // decode packet
140             let slice = DoubleVlanSlice::from_slice(&data).unwrap();
141 
142             // check debug output
143             prop_assert_eq!(
144                 format!("{:?}", slice),
145                 format!(
146                     "DoubleVlanSlice {{ outer: {:?}, inner: {:?}, payload: {:?} }}",
147                     slice.outer().to_header(),
148                     slice.inner().to_header(),
149                     slice.payload(),
150                 )
151             );
152             prop_assert_eq!(slice.clone(), slice);
153         }
154     }
155 
156     proptest! {
157         #[test]
158         fn getters(vlan in vlan_double_any()) {
159             let payload: [u8;8] = [1,2,3,4,5,6,7,8];
160             let mut data = Vec::with_capacity(
161                 vlan.header_len() +
162                 payload.len()
163             );
164             data.extend_from_slice(&vlan.to_bytes());
165             data.extend_from_slice(&payload);
166 
167             let slice = DoubleVlanSlice::from_slice(&data).unwrap();
168             assert_eq!(&data, slice.slice());
169             assert_eq!(&data, slice.outer().slice());
170             assert_eq!(vlan.outer, slice.outer().to_header());
171             assert_eq!(&data[SingleVlanHeader::LEN..], slice.inner().slice());
172             assert_eq!(vlan.inner, slice.inner().to_header());
173             assert_eq!(vlan, slice.to_header());
174             assert_eq!(
175                 EtherPayloadSlice{
176                     ether_type: vlan.inner.ether_type,
177                     payload: &payload
178                 },
179                 slice.payload()
180             );
181             assert_eq!(&payload, slice.payload_slice());
182             assert_eq!(DoubleVlanHeader::LEN, slice.header_len());
183         }
184     }
185 
186     proptest! {
187         #[test]
188         fn from_slice(
189             vlan in vlan_double_any(),
190             ether_type_non_vlan in ether_type_any().prop_filter(
191                 "ether_type must not be a vlan ether type",
192                 |v| !VlanHeader::VLAN_ETHER_TYPES.iter().any(|&x| v == &x)
193             )
194         ) {
195             use err::double_vlan::{HeaderError::*, HeaderSliceError::*};
196 
197             let payload: [u8;10] = [1,2,3,4,5,6,7,8,9,10];
198             let data = {
199                 let mut data = Vec::with_capacity(
200                     vlan.header_len() +
201                     payload.len()
202                 );
203                 data.extend_from_slice(&vlan.to_bytes());
204                 data.extend_from_slice(&payload);
205                 data
206             };
207 
208             // normal decode
209             {
210                 let slice = DoubleVlanSlice::from_slice(&data).unwrap();
211                 assert_eq!(slice.to_header(), vlan);
212                 assert_eq!(slice.payload_slice(), &payload);
213             }
214 
215             // length error
216             for len in 0..DoubleVlanHeader::LEN {
217                 assert_eq!(
218                     DoubleVlanSlice::from_slice(&data[..len]).unwrap_err(),
219                     Len(LenError{
220                         required_len: DoubleVlanHeader::LEN,
221                         len,
222                         len_source: LenSource::Slice,
223                         layer: Layer::VlanHeader,
224                         layer_start_offset: 0
225                     })
226                 );
227             }
228 
229             // mismatching outer ether type
230             {
231                 let mut bad_data = data.clone();
232                 let e_be = ether_type_non_vlan.0.to_be_bytes();
233                 bad_data[2] = e_be[0];
234                 bad_data[3] = e_be[1];
235                 assert_eq!(
236                     DoubleVlanSlice::from_slice(&bad_data).unwrap_err(),
237                     Content(NonVlanEtherType{
238                         unexpected_ether_type: ether_type_non_vlan,
239                     })
240                 );
241             }
242         }
243     }
244 }
245