1 use crate::*;
2 
3 /// Helper class for slicing packets
4 pub(crate) struct SlicedPacketCursor<'a> {
5     pub slice: &'a [u8],
6     pub offset: usize,
7     pub len_source: LenSource,
8     pub result: SlicedPacket<'a>,
9 }
10 
11 impl<'a> SlicedPacketCursor<'a> {
new(slice: &'a [u8]) -> SlicedPacketCursor<'a>12     pub fn new(slice: &'a [u8]) -> SlicedPacketCursor<'a> {
13         SlicedPacketCursor {
14             slice,
15             offset: 0,
16             len_source: LenSource::Slice,
17             result: SlicedPacket {
18                 link: None,
19                 vlan: None,
20                 net: None,
21                 transport: None,
22             },
23         }
24     }
25 
move_by(&mut self, len: usize)26     fn move_by(&mut self, len: usize) {
27         unsafe {
28             use core::slice::from_raw_parts;
29             self.slice = from_raw_parts(self.slice.as_ptr().add(len), self.slice.len() - len);
30         }
31         self.offset += len;
32     }
33 
slice_ethernet2(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>34     pub fn slice_ethernet2(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> {
35         use err::packet::SliceError::*;
36         use ether_type::*;
37         use LinkSlice::*;
38 
39         let result = Ethernet2Slice::from_slice_without_fcs(self.slice)
40             .map_err(|err| Len(err.add_offset(self.offset)))?;
41 
42         //cache the ether_type for later
43         let ether_type = result.ether_type();
44 
45         //set the new data
46         self.move_by(result.header_len());
47         self.result.link = Some(Ethernet2(result));
48 
49         //continue parsing (if required)
50         match ether_type {
51             IPV4 => self.slice_ipv4(),
52             IPV6 => self.slice_ipv6(),
53             VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => self.slice_vlan(),
54             _ => Ok(self.result),
55         }
56     }
57 
slice_linux_sll(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>58     pub fn slice_linux_sll(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> {
59         use err::packet::SliceError::*;
60 
61         let result = LinuxSllSlice::from_slice(self.slice).map_err(|err| match err {
62             err::linux_sll::HeaderSliceError::Len(len) => Len(len.add_offset(self.offset)),
63             err::linux_sll::HeaderSliceError::Content(content) => {
64                 err::packet::SliceError::LinuxSll(content)
65             }
66         })?;
67 
68         //cache the protocol type for later
69         let protocol_type = result.protocol_type();
70 
71         //set the new data
72         self.move_by(result.header_len());
73         self.result.link = Some(LinkSlice::LinuxSll(result));
74 
75         //continue parsing (if required)
76         match protocol_type {
77             LinuxSllProtocolType::EtherType(EtherType::IPV4) => self.slice_ipv4(),
78             LinuxSllProtocolType::EtherType(EtherType::IPV6) => self.slice_ipv6(),
79             _ => Ok(self.result),
80         }
81     }
82 
slice_vlan(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>83     pub fn slice_vlan(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> {
84         use err::packet::SliceError::*;
85         use ether_type::*;
86         use VlanSlice::*;
87 
88         // cache the starting slice so the later combining
89         // of outer & inner vlan is defined behavior (for miri)
90         let outer_start_slice = self.slice;
91         let outer = SingleVlanSlice::from_slice(self.slice)
92             .map_err(|err| Len(err.add_offset(self.offset)))?;
93         self.result.vlan = Some(SingleVlan(outer.clone()));
94         self.move_by(outer.header_len());
95 
96         //check if it is a double vlan header
97         match outer.ether_type() {
98             //in case of a double vlan header continue with the inner
99             VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => {
100                 let inner = SingleVlanSlice::from_slice(self.slice)
101                     .map_err(|err| Len(err.add_offset(self.offset)))?;
102                 self.move_by(inner.header_len());
103 
104                 let inner_ether_type = inner.ether_type();
105                 self.result.vlan = Some(DoubleVlan(DoubleVlanSlice {
106                     slice: outer_start_slice,
107                 }));
108 
109                 match inner_ether_type {
110                     IPV4 => self.slice_ipv4(),
111                     IPV6 => self.slice_ipv6(),
112                     _ => Ok(self.result),
113                 }
114             }
115             IPV4 => self.slice_ipv4(),
116             IPV6 => self.slice_ipv6(),
117             _ => Ok(self.result),
118         }
119     }
120 
slice_ip(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>121     pub fn slice_ip(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> {
122         use err::packet::SliceError::*;
123 
124         // slice header, extension headers and identify payload range
125         let ip = IpSlice::from_slice(self.slice).map_err(|err| {
126             use err::ip::SliceError as I;
127             match err {
128                 I::Len(mut err) => {
129                     err.layer_start_offset += self.offset;
130                     Len(err)
131                 }
132                 I::IpHeaders(err) => match err {
133                     err::ip::HeadersError::Ip(err) => Ip(err),
134                     err::ip::HeadersError::Ipv4Ext(err) => Ipv4Exts(err),
135                     err::ip::HeadersError::Ipv6Ext(err) => Ipv6Exts(err),
136                 },
137             }
138         })?;
139 
140         // safe data needed
141         let payload = ip.payload().clone();
142 
143         // set the new data
144         self.offset += unsafe {
145             // SAFETY: The payload is a subslice of self.slice.
146             // therefor calculating the offset from it is safe and
147             // the result should always be a positive number.
148             payload.payload.as_ptr().offset_from(self.slice.as_ptr()) as usize
149         };
150         self.len_source = payload.len_source;
151         self.slice = payload.payload;
152         self.result.net = Some(ip.into());
153 
154         // continue to the lower layers
155         if payload.fragmented {
156             Ok(self.result)
157         } else {
158             match payload.ip_number {
159                 ip_number::ICMP => self.slice_icmp4().map_err(Len),
160                 ip_number::UDP => self.slice_udp().map_err(Len),
161                 ip_number::TCP => self.slice_tcp().map_err(|err| {
162                     use err::tcp::HeaderSliceError as I;
163                     match err {
164                         I::Len(err) => Len(err),
165                         I::Content(err) => Tcp(err),
166                     }
167                 }),
168                 ip_number::IPV6_ICMP => self.slice_icmp6().map_err(Len),
169                 _ => Ok(self.result),
170             }
171         }
172     }
173 
slice_ipv4(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>174     pub fn slice_ipv4(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> {
175         use err::packet::SliceError::*;
176 
177         // slice ipv4 header & extension headers
178         let ipv4 = Ipv4Slice::from_slice(self.slice).map_err(|err| {
179             use err::ipv4::SliceError as I;
180             match err {
181                 I::Len(mut err) => {
182                     err.layer_start_offset += self.offset;
183                     Len(err)
184                 }
185                 I::Header(err) => Ipv4(err),
186                 I::Exts(err) => Ipv4Exts(err),
187             }
188         })?;
189 
190         // safe data needed in following steps
191         let payload = ipv4.payload().clone();
192 
193         // set the new data
194         self.offset += unsafe {
195             // SAFETY: The payload is a subslice of self.slice.
196             // therefor calculating the offset from it is safe and
197             // the result should always be a positive number.
198             payload.payload.as_ptr().offset_from(self.slice.as_ptr()) as usize
199         };
200         self.len_source = payload.len_source;
201         self.slice = payload.payload;
202         self.result.net = Some(NetSlice::Ipv4(ipv4));
203 
204         if payload.fragmented {
205             Ok(self.result)
206         } else {
207             match payload.ip_number {
208                 ip_number::UDP => self.slice_udp().map_err(Len),
209                 ip_number::TCP => self.slice_tcp().map_err(|err| {
210                     use err::tcp::HeaderSliceError as I;
211                     match err {
212                         I::Len(err) => Len(err),
213                         I::Content(err) => Tcp(err),
214                     }
215                 }),
216                 ip_number::ICMP => self.slice_icmp4().map_err(Len),
217                 ip_number::IPV6_ICMP => self.slice_icmp6().map_err(Len),
218                 _ => Ok(self.result),
219             }
220         }
221     }
222 
slice_ipv6(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>223     pub fn slice_ipv6(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> {
224         use err::packet::SliceError::*;
225 
226         let ipv6 = Ipv6Slice::from_slice(self.slice).map_err(|err| {
227             use err::ipv6::SliceError as I;
228             match err {
229                 I::Len(mut err) => {
230                     err.layer_start_offset += self.offset;
231                     Len(err)
232                 }
233                 I::Header(err) => Ipv6(err),
234                 I::Exts(err) => Ipv6Exts(err),
235             }
236         })?;
237 
238         // safe data needed in following steps
239         let payload = ipv6.payload().clone();
240 
241         // set the new data
242         self.offset += unsafe {
243             // SAFETY: The payload is a subslice of self.slice.
244             // therefor calculating the offset from it is safe and
245             // the result should always be a positive number.
246             ipv6.payload()
247                 .payload
248                 .as_ptr()
249                 .offset_from(self.slice.as_ptr()) as usize
250         };
251         self.len_source = ipv6.payload().len_source;
252         self.slice = ipv6.payload().payload;
253         self.result.net = Some(NetSlice::Ipv6(ipv6));
254 
255         // only try to decode the transport layer if the payload
256         // is not fragmented
257         if payload.fragmented {
258             Ok(self.result)
259         } else {
260             //parse the data bellow
261             match payload.ip_number {
262                 ip_number::ICMP => self.slice_icmp4().map_err(Len),
263                 ip_number::UDP => self.slice_udp().map_err(Len),
264                 ip_number::TCP => self.slice_tcp().map_err(|err| {
265                     use err::tcp::HeaderSliceError as I;
266                     match err {
267                         I::Len(err) => Len(err),
268                         I::Content(err) => Tcp(err),
269                     }
270                 }),
271                 ip_number::IPV6_ICMP => self.slice_icmp6().map_err(Len),
272                 _ => Ok(self.result),
273             }
274         }
275     }
276 
slice_icmp4(mut self) -> Result<SlicedPacket<'a>, err::LenError>277     pub fn slice_icmp4(mut self) -> Result<SlicedPacket<'a>, err::LenError> {
278         use crate::TransportSlice::*;
279 
280         let result = Icmpv4Slice::from_slice(self.slice).map_err(|mut err| {
281             err.layer_start_offset += self.offset;
282             if LenSource::Slice == err.len_source {
283                 err.len_source = self.len_source;
284             }
285             err
286         })?;
287 
288         //set the new data
289         self.move_by(result.slice().len());
290         self.result.transport = Some(Icmpv4(result.clone()));
291 
292         Ok(self.result)
293     }
294 
slice_icmp6(mut self) -> Result<SlicedPacket<'a>, err::LenError>295     pub fn slice_icmp6(mut self) -> Result<SlicedPacket<'a>, err::LenError> {
296         use crate::TransportSlice::*;
297 
298         let result = Icmpv6Slice::from_slice(self.slice).map_err(|mut err| {
299             err.layer_start_offset += self.offset;
300             if LenSource::Slice == err.len_source {
301                 err.len_source = self.len_source;
302             }
303             err
304         })?;
305 
306         //set the new data
307         self.move_by(result.slice().len());
308         self.result.transport = Some(Icmpv6(result.clone()));
309 
310         //done
311         Ok(self.result)
312     }
313 
slice_udp(mut self) -> Result<SlicedPacket<'a>, err::LenError>314     pub fn slice_udp(mut self) -> Result<SlicedPacket<'a>, err::LenError> {
315         use crate::TransportSlice::*;
316 
317         let result = UdpSlice::from_slice(self.slice).map_err(|mut err| {
318             err.layer_start_offset += self.offset;
319             if LenSource::Slice == err.len_source {
320                 err.len_source = self.len_source;
321             }
322             err
323         })?;
324 
325         //set the new data
326         self.move_by(result.slice().len());
327         self.result.transport = Some(Udp(result));
328 
329         // done
330         Ok(self.result)
331     }
332 
slice_tcp(mut self) -> Result<SlicedPacket<'a>, err::tcp::HeaderSliceError>333     pub fn slice_tcp(mut self) -> Result<SlicedPacket<'a>, err::tcp::HeaderSliceError> {
334         use crate::TransportSlice::*;
335 
336         let result = TcpSlice::from_slice(self.slice).map_err(|mut err| {
337             use err::tcp::HeaderSliceError::Len;
338             if let Len(err) = &mut err {
339                 err.layer_start_offset += self.offset;
340                 if LenSource::Slice == err.len_source {
341                     err.len_source = self.len_source;
342                 }
343             }
344             err
345         })?;
346 
347         //set the new data
348         self.move_by(result.slice().len());
349         self.result.transport = Some(Tcp(result));
350 
351         // done
352         Ok(self.result)
353     }
354 }
355