1 use crate::{
2     err::{packet::SliceError, Layer, LenError},
3     *,
4 };
5 
6 /// Decoded packet headers (data link layer and lower) with lax length checks.
7 ///
8 /// You can use
9 ///
10 /// * [`LaxPacketHeaders::from_ethernet`]
11 /// * [`LaxPacketHeaders::from_ether_type`]
12 /// * [`LaxPacketHeaders::from_ip`]
13 ///
14 /// depending on your starting header to parse the headers in a slice and get this
15 /// struct as a result.
16 #[derive(Clone, Debug, Eq, PartialEq)]
17 pub struct LaxPacketHeaders<'a> {
18     /// Ethernet II header if present.
19     pub link: Option<LinkHeader>,
20 
21     /// Single or double vlan headers if present.
22     pub vlan: Option<VlanHeader>,
23 
24     /// IPv4 or IPv6 header and IP extension headers if present.
25     pub net: Option<NetHeaders>,
26 
27     /// TCP or UDP header if present.
28     pub transport: Option<TransportHeader>,
29 
30     /// Payload of the last parsed layer.
31     pub payload: LaxPayloadSlice<'a>,
32 
33     /// Error that stopped the parsing and the layer on which the stop occurred.
34     pub stop_err: Option<(err::packet::SliceError, Layer)>,
35 }
36 
37 impl<'a> LaxPacketHeaders<'a> {
38     /// Separates a network packet into different headers from the ethernet header
39     /// downwards with lax length checks and non-terminating errors.
40     ///
41     /// # Example
42     ///
43     /// Basic usage:
44     ///
45     ///```
46     /// # use etherparse::{Ethernet2Header, PacketBuilder};
47     /// # let builder = PacketBuilder::
48     /// #    ethernet2([1,2,3,4,5,6],     //source mac
49     /// #               [7,8,9,10,11,12]) //destionation mac
50     /// #    .ipv4([192,168,1,1], //source ip
51     /// #          [192,168,1,2], //destination ip
52     /// #          20)            //time to life
53     /// #    .udp(21,    //source port
54     /// #         1234); //desitnation port
55     /// # // payload of the udp packet
56     /// # let payload = [1,2,3,4,5,6,7,8];
57     /// # // get some memory to store the serialized data
58     /// # let mut packet = Vec::<u8>::with_capacity(
59     /// #     builder.size(payload.len())
60     /// # );
61     /// # builder.write(&mut packet, &payload).unwrap();
62     /// #
63     /// use etherparse::{ether_type, LaxPacketHeaders, LenSource, LaxPayloadSlice};
64     ///
65     /// match LaxPacketHeaders::from_ethernet(&packet) {
66     ///     Err(value) => {
67     ///         // An error is returned in case the ethernet II header could
68     ///         // not be parsed (other errors are stored in the "stop_err" field)
69     ///         println!("Err {:?}", value)
70     ///     },
71     ///     Ok(value) => {
72     ///         if let Some((stop_err, error_layer)) = value.stop_err.as_ref() {
73     ///             // error was encountered after parsing the ethernet 2 header
74     ///             println!("Error on layer {}: {:?}", error_layer, stop_err);
75     ///         }
76     ///
77     ///         // parts that could be parsed without error
78     ///         println!("link: {:?}", value.link);
79     ///         println!("vlan: {:?}", value.vlan);
80     ///         println!("net: {:?}", value.net);
81     ///         println!("transport: {:?}", value.transport);
82     ///
83     ///         // net (ip) & transport (udp or tcp)
84     ///         println!("net: {:?}", value.net);
85     ///         match value.payload {
86     ///             LaxPayloadSlice::Ether(e) => {
87     ///                 println!("ether payload (ether type {:?}): {:?}", e.ether_type, e.payload);
88     ///             }
89     ///             LaxPayloadSlice::Ip(ip) => {
90     ///                 println!("IP payload (IP number {:?}): {:?}", ip.ip_number, ip.payload);
91     ///                 if ip.incomplete {
92     ///                     println!("  IP payload incomplete (length in IP header indicated more data should be present)");
93     ///                 }
94     ///                 if ip.fragmented {
95     ///                     println!("  IP payload fragmented");
96     ///                 }
97     ///             }
98     ///             LaxPayloadSlice::Udp{ payload, incomplete } => {
99     ///                 println!("UDP payload: {:?}", payload);
100     ///                 if incomplete {
101     ///                     println!("  UDP payload incomplete (length in UDP or IP header indicated more data should be present)");
102     ///                 }
103     ///             }
104     ///             LaxPayloadSlice::Tcp{ payload, incomplete } => {
105     ///                 println!("TCP payload: {:?}", payload);
106     ///                 if incomplete {
107     ///                     println!("  TCP payload incomplete (length in IP header indicated more data should be present)");
108     ///                 }
109     ///             }
110     ///             LaxPayloadSlice::Icmpv4{ payload, incomplete } => {
111     ///                 println!("Icmpv4 payload: {:?}", payload);
112     ///                 if incomplete {
113     ///                     println!("  Icmpv4 payload incomplete (length in IP header indicated more data should be present)");
114     ///                 }
115     ///             }
116     ///             LaxPayloadSlice::Icmpv6{ payload, incomplete } => {
117     ///                 println!("Icmpv6 payload: {:?}", payload);
118     ///                 if incomplete {
119     ///                     println!("  Icmpv6 payload incomplete (length in IP header indicated more data should be present)");
120     ///                 }
121     ///             }
122     ///         }
123     ///     }
124     /// }
125     ///
126     /// ```
from_ethernet(slice: &'a [u8]) -> Result<LaxPacketHeaders<'a>, err::LenError>127     pub fn from_ethernet(slice: &'a [u8]) -> Result<LaxPacketHeaders<'a>, err::LenError> {
128         let (ethernet, rest) = Ethernet2Header::from_slice(slice)?;
129         let mut result = Self::from_ether_type(ethernet.ether_type, rest);
130         result.link = Some(LinkHeader::Ethernet2(ethernet));
131         if let Some((SliceError::Len(l), _)) = result.stop_err.as_mut() {
132             l.layer_start_offset += Ethernet2Header::LEN;
133         }
134         Ok(result)
135     }
136 
137     /// Separates a network packet into different headers using
138     /// the given `ether_type` number to identify the first header with lax length
139     /// checks and non-terminating errors.
140     ///
141     /// The result is returned as a [`LaxSlicedPacket`] struct. Currently supported
142     /// ether type numbers are:
143     ///
144     /// * `ether_type::IPV4`
145     /// * `ether_type::IPV6`
146     /// * `ether_type::VLAN_TAGGED_FRAME`
147     /// * `ether_type::PROVIDER_BRIDGING`
148     /// * `ether_type::VLAN_DOUBLE_TAGGED_FRAME`
149     ///
150     /// If an unsupported ether type is given the given slice will be set as payload
151     /// and all other fields will be set to `None`.
152     ///
153     /// # Example
154     ///
155     /// Basic usage:
156     ///
157     ///```
158     /// # use etherparse::{Ethernet2Header, PacketBuilder};
159     /// # let builder = PacketBuilder::
160     /// #    ethernet2([1,2,3,4,5,6],     //source mac
161     /// #               [7,8,9,10,11,12]) //destionation mac
162     /// #    .ipv4([192,168,1,1], //source ip
163     /// #          [192,168,1,2], //destination ip
164     /// #          20)            //time to life
165     /// #    .udp(21,    //source port
166     /// #         1234); //desitnation port
167     /// # // payload of the udp packet
168     /// # let payload = [1,2,3,4,5,6,7,8];
169     /// # // get some memory to store the serialized data
170     /// # let mut complete_packet = Vec::<u8>::with_capacity(
171     /// #     builder.size(payload.len())
172     /// # );
173     /// # builder.write(&mut complete_packet, &payload).unwrap();
174     /// # // skip ethernet 2 header so we can parse from there downwards
175     /// # let packet = &complete_packet[Ethernet2Header::LEN..];
176     /// #
177     /// use etherparse::{ether_type, LaxPacketHeaders, LenSource, LaxPayloadSlice};
178     ///
179     /// let value = LaxPacketHeaders::from_ether_type(ether_type::IPV4, &packet);
180     ///
181     /// if let Some((stop_err, error_layer)) = value.stop_err.as_ref() {
182     ///     // error was encountered after parsing the ethernet 2 header
183     ///     println!("Error on layer {}: {:?}", error_layer, stop_err);
184     /// }
185     ///
186     /// // link is unfilled
187     /// assert_eq!(value.link, None);
188     ///
189     /// // parts that could be parsed without error
190     /// println!("vlan: {:?}", value.vlan);
191     /// println!("net: {:?}", value.net);
192     /// println!("transport: {:?}", value.transport);
193     ///
194     /// // net (ip) & transport (udp or tcp)
195     /// println!("net: {:?}", value.net);
196     /// match value.payload {
197     ///     LaxPayloadSlice::Ether(e) => {
198     ///         println!("ether payload (ether type {:?}): {:?}", e.ether_type, e.payload);
199     ///     }
200     ///     LaxPayloadSlice::Ip(ip) => {
201     ///         println!("IP payload (IP number {:?}): {:?}", ip.ip_number, ip.payload);
202     ///         if ip.incomplete {
203     ///             println!("  IP payload incomplete (length in IP header indicated more data should be present)");
204     ///         }
205     ///         if ip.fragmented {
206     ///             println!("  IP payload fragmented");
207     ///         }
208     ///     }
209     ///     LaxPayloadSlice::Udp{ payload, incomplete } => {
210     ///         println!("UDP payload: {:?}", payload);
211     ///         if incomplete {
212     ///             println!("  UDP payload incomplete (length in UDP or IP header indicated more data should be present)");
213     ///         }
214     ///     }
215     ///     LaxPayloadSlice::Tcp{ payload, incomplete } => {
216     ///         println!("TCP payload: {:?}", payload);
217     ///         if incomplete {
218     ///             println!("  TCP payload incomplete (length in IP header indicated more data should be present)");
219     ///         }
220     ///     }
221     ///     LaxPayloadSlice::Icmpv4{ payload, incomplete } => {
222     ///         println!("Icmpv4 payload: {:?}", payload);
223     ///         if incomplete {
224     ///             println!("  Icmpv4 payload incomplete (length in IP header indicated more data should be present)");
225     ///         }
226     ///     }
227     ///     LaxPayloadSlice::Icmpv6{ payload, incomplete } => {
228     ///         println!("Icmpv6 payload: {:?}", payload);
229     ///         if incomplete {
230     ///             println!("  Icmpv6 payload incomplete (length in IP header indicated more data should be present)");
231     ///         }
232     ///     }
233     /// }
234     /// ```
from_ether_type(mut ether_type: EtherType, slice: &'a [u8]) -> LaxPacketHeaders<'a>235     pub fn from_ether_type(mut ether_type: EtherType, slice: &'a [u8]) -> LaxPacketHeaders<'a> {
236         use err::packet::SliceError::*;
237 
238         let mut rest = slice;
239         let mut offset = 0;
240         let mut result = LaxPacketHeaders {
241             link: None,
242             vlan: None,
243             net: None,
244             transport: None,
245             payload: LaxPayloadSlice::Ether(EtherPayloadSlice {
246                 ether_type,
247                 payload: rest,
248             }),
249             stop_err: None,
250         };
251 
252         // parse vlan header(s)
253         use ether_type::*;
254 
255         result.vlan = match ether_type {
256             VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => {
257                 use crate::VlanHeader::*;
258                 let (outer, outer_rest) = match SingleVlanHeader::from_slice(rest) {
259                     Ok(value) => value,
260                     Err(err) => {
261                         result.stop_err = Some((Len(err), Layer::VlanHeader));
262                         return result;
263                     }
264                 };
265 
266                 // set the rest & ether_type for the following operations
267                 rest = outer_rest;
268                 offset += SingleVlanHeader::LEN;
269                 ether_type = outer.ether_type;
270                 result.payload = LaxPayloadSlice::Ether(EtherPayloadSlice {
271                     ether_type,
272                     payload: rest,
273                 });
274 
275                 // parse second vlan header if present
276                 match ether_type {
277                     // second vlan tagging header
278                     VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => {
279                         let (inner, inner_rest) = match SingleVlanHeader::from_slice(rest) {
280                             Ok(value) => value,
281                             Err(mut err) => {
282                                 err.layer_start_offset += SingleVlanHeader::LEN;
283                                 result.vlan = Some(VlanHeader::Single(outer.clone()));
284                                 result.stop_err = Some((Len(err), Layer::VlanHeader));
285                                 return result;
286                             }
287                         };
288 
289                         // set the rest & ether_type for the following operations
290                         rest = inner_rest;
291                         offset += SingleVlanHeader::LEN;
292                         ether_type = inner.ether_type;
293                         result.payload = LaxPayloadSlice::Ether(EtherPayloadSlice {
294                             ether_type,
295                             payload: rest,
296                         });
297 
298                         Some(Double(DoubleVlanHeader { outer, inner }))
299                     }
300                     // no second vlan header detected -> single vlan header
301                     _ => Some(Single(outer)),
302                 }
303             }
304             // no vlan header
305             _ => None,
306         };
307 
308         // parse ip
309         match ether_type {
310             IPV4 | IPV6 => match result.add_ip(offset, rest) {
311                 Ok(_) => {}
312                 Err(err) => {
313                     use err::ip::LaxHeaderSliceError as I;
314                     result.stop_err = Some(match err {
315                         I::Len(mut l) => {
316                             l.layer_start_offset += offset;
317                             (Len(l), Layer::IpHeader)
318                         }
319                         I::Content(c) => (Ip(c), Layer::IpHeader),
320                     });
321                     return result;
322                 }
323             },
324             _ => {}
325         };
326 
327         result
328     }
329 
330     /// Separates a network packet slice into different headers from the
331     /// ip header downwards with lax length checks and will still return
332     /// a result even if an error is encountered in a layer (except IP).
333     ///
334     /// This function has two main differences to [`PacketHeaders::from_ip_slice`]:
335     ///
336     /// * Errors encountered bellow the IpHeader will only stop the parsing and
337     ///   return an `Ok` with the successfully parsed parts and the error as optional.
338     ///   Only if an unrecoverable error is encountered in the IP header itself an
339     ///   `Err` is returned.
340     /// * Length in the IP header & UDP headers are allowed to be inconsistent with the
341     ///   given slice length (e.g. data is missing from the slice). In this case it falls
342     ///   back to the length of slice. See [`LaxIpSlice::from_slice`] for a detailed
343     ///   description of when the slice length is used as a fallback.
344     ///
345     /// The result is returned as a [`SlicedPacket`] struct. This function
346     /// assumes the given data starts with an IPv4 or IPv6 header.
347     ///
348     /// # Examples
349     ///
350     /// Basic usage:
351     ///
352     ///```
353     /// # use etherparse::{PacketBuilder, Ethernet2Header};
354     /// # let builder = PacketBuilder::
355     /// #    ipv4([192,168,1,1], //source ip
356     /// #         [192,168,1,2], //destination ip
357     /// #         20)            //time to life
358     /// #    .udp(21,    //source port
359     /// #         1234); //desitnation port
360     /// # //payload of the udp packet
361     /// # let payload = [1,2,3,4,5,6,7,8];
362     /// # // get some memory to store the serialized data
363     /// # let mut complete_packet = Vec::<u8>::with_capacity(
364     /// #     builder.size(payload.len())
365     /// # );
366     /// # builder.write(&mut complete_packet, &payload).unwrap();
367     /// # // skip ethernet 2 header so we can parse from there downwards
368     /// # let packet = &complete_packet[Ethernet2Header::LEN..];
369     /// #
370     /// use etherparse::{ether_type, LaxPacketHeaders, LenSource, LaxPayloadSlice};
371     ///
372     /// match LaxPacketHeaders::from_ip(&packet) {
373     ///     Err(value) => {
374     ///         // An error is returned in case the ip header could
375     ///         // not be parsed (other errors are stored in the "stop_err" field)
376     ///         println!("Err {:?}", value)
377     ///     },
378     ///     Ok(value) => {
379     ///         if let Some((stop_err, error_layer)) = value.stop_err.as_ref() {
380     ///             // error was encountered after parsing the ethernet 2 header
381     ///             println!("Error on layer {}: {:?}", error_layer, stop_err);
382     ///         }
383     ///
384     ///         // link & vlan is unfilled
385     ///         assert_eq!(value.link, None);
386     ///         assert_eq!(value.vlan, None);
387     ///
388     ///         // parts that could be parsed without error
389     ///         println!("net: {:?}", value.net);
390     ///         println!("transport: {:?}", value.transport);
391     ///
392     ///         // net (ip) & transport (udp or tcp)
393     ///         println!("net: {:?}", value.net);
394     ///         match value.payload {
395     ///             // if you parse from IP down there will be no ether payload
396     ///             LaxPayloadSlice::Ether(e) => unreachable!(),
397     ///             LaxPayloadSlice::Ip(ip) => {
398     ///                 println!("IP payload (IP number {:?}): {:?}", ip.ip_number, ip.payload);
399     ///                 if ip.incomplete {
400     ///                     println!("  IP payload incomplete (length in IP header indicated more data should be present)");
401     ///                 }
402     ///                 if ip.fragmented {
403     ///                     println!("  IP payload fragmented");
404     ///                 }
405     ///             }
406     ///             LaxPayloadSlice::Udp{ payload, incomplete } => {
407     ///                 println!("UDP payload: {:?}", payload);
408     ///                 if incomplete {
409     ///                     println!("  UDP payload incomplete (length in UDP or IP header indicated more data should be present)");
410     ///                 }
411     ///             }
412     ///             LaxPayloadSlice::Tcp{ payload, incomplete } => {
413     ///                 println!("TCP payload: {:?}", payload);
414     ///                 if incomplete {
415     ///                     println!("  TCP payload incomplete (length in IP header indicated more data should be present)");
416     ///                 }
417     ///             }
418     ///             LaxPayloadSlice::Icmpv4{ payload, incomplete } => {
419     ///                 println!("Icmpv4 payload: {:?}", payload);
420     ///                 if incomplete {
421     ///                     println!("  Icmpv4 payload incomplete (length in IP header indicated more data should be present)");
422     ///                 }
423     ///             }
424     ///             LaxPayloadSlice::Icmpv6{ payload, incomplete } => {
425     ///                 println!("Icmpv6 payload: {:?}", payload);
426     ///                 if incomplete {
427     ///                     println!("  Icmpv6 payload incomplete (length in IP header indicated more data should be present)");
428     ///                 }
429     ///             }
430     ///         }
431     ///     }
432     /// }
433     ///
434     /// ```
from_ip(slice: &'a [u8]) -> Result<LaxPacketHeaders<'a>, err::ip::LaxHeaderSliceError>435     pub fn from_ip(slice: &'a [u8]) -> Result<LaxPacketHeaders<'a>, err::ip::LaxHeaderSliceError> {
436         let mut result = Self {
437             link: None,
438             vlan: None,
439             net: None,
440             transport: None,
441             // dummy initialize (will be overwritten if add_ip is successfull)
442             payload: LaxPayloadSlice::Udp {
443                 payload: &[],
444                 incomplete: true,
445             },
446             stop_err: None,
447         };
448         result.add_ip(0, slice)?;
449         Ok(result)
450     }
451 
add_ip( &mut self, offset: usize, slice: &'a [u8], ) -> Result<(), err::ip::LaxHeaderSliceError>452     fn add_ip(
453         &mut self,
454         offset: usize,
455         slice: &'a [u8],
456     ) -> Result<(), err::ip::LaxHeaderSliceError> {
457         use err::packet::SliceError::*;
458 
459         // read ipv4 header & extensions and payload slice
460         let (ip, ip_payload, stop_err) = IpHeaders::from_slice_lax(slice)?;
461 
462         // set the next
463         self.net = Some(ip.into());
464         self.payload = LaxPayloadSlice::Ip(ip_payload.clone());
465 
466         // if a stop error was encountered return it
467         if let Some((err, layer)) = stop_err {
468             use err::ip_exts::HeaderError as IC;
469             use err::ip_exts::HeadersSliceError as I;
470 
471             self.stop_err = Some((
472                 match err {
473                     I::Len(mut l) => {
474                         l.layer_start_offset += offset;
475                         l.len_source = ip_payload.len_source;
476                         Len(l)
477                     }
478                     I::Content(e) => match e {
479                         IC::Ipv4Ext(e) => SliceError::Ipv4Exts(e),
480                         IC::Ipv6Ext(e) => SliceError::Ipv6Exts(e),
481                     },
482                 },
483                 layer,
484             ));
485             return Ok(());
486         }
487 
488         // update the offset with the ip headers
489         let offset = offset + ((ip_payload.payload.as_ptr() as usize) - (slice.as_ptr() as usize));
490 
491         // decode transport layer
492         if false == ip_payload.fragmented {
493             // helper function to set the len source in len errors
494             let add_len_source = |mut len_error: LenError| -> err::packet::SliceError {
495                 // only change the len source if the lower layer has not set it
496                 if LenSource::Slice == len_error.len_source {
497                     len_error.len_source = ip_payload.len_source;
498                     len_error.layer_start_offset += offset;
499                 }
500                 err::packet::SliceError::Len(len_error)
501             };
502 
503             use crate::ip_number::*;
504             use err::tcp::HeaderSliceError::*;
505             match ip_payload.ip_number {
506                 ICMP => match Icmpv4Slice::from_slice(ip_payload.payload) {
507                     Ok(i) => {
508                         self.transport = Some(TransportHeader::Icmpv4(i.header()));
509                         self.payload = LaxPayloadSlice::Icmpv4 {
510                             payload: i.payload(),
511                             incomplete: ip_payload.incomplete,
512                         };
513                     }
514                     Err(e) => {
515                         self.stop_err = Some((add_len_source(e), Layer::Icmpv4));
516                     }
517                 },
518                 IPV6_ICMP => match Icmpv6Slice::from_slice(ip_payload.payload) {
519                     Ok(i) => {
520                         self.transport = Some(TransportHeader::Icmpv6(i.header()));
521                         self.payload = LaxPayloadSlice::Icmpv6 {
522                             payload: i.payload(),
523                             incomplete: ip_payload.incomplete,
524                         };
525                     }
526                     Err(e) => {
527                         self.stop_err = Some((add_len_source(e), Layer::Icmpv6));
528                     }
529                 },
530                 UDP => {
531                     match UdpSlice::from_slice_lax(ip_payload.payload) {
532                         Ok(u) => {
533                             self.transport = Some(TransportHeader::Udp(u.to_header()));
534                             self.payload = LaxPayloadSlice::Udp {
535                                 payload: u.payload(),
536                                 // TODO also check the udp header length
537                                 incomplete: ip_payload.incomplete,
538                             };
539                         }
540                         Err(e) => {
541                             self.stop_err = Some((add_len_source(e), Layer::UdpHeader));
542                         }
543                     }
544                 }
545                 TCP => match TcpHeader::from_slice(ip_payload.payload) {
546                     Ok(t) => {
547                         self.transport = Some(TransportHeader::Tcp(t.0));
548                         self.payload = LaxPayloadSlice::Tcp {
549                             payload: t.1,
550                             incomplete: ip_payload.incomplete,
551                         };
552                     }
553                     Err(e) => match e {
554                         Len(l) => {
555                             self.stop_err = Some((add_len_source(l), Layer::TcpHeader));
556                         }
557                         Content(c) => {
558                             self.stop_err = Some((SliceError::Tcp(c), Layer::TcpHeader));
559                         }
560                     },
561                 },
562                 _ => {}
563             }
564         }
565         Ok(())
566     }
567 }
568 
569 #[cfg(test)]
570 mod test {
571     use super::*;
572     use crate::test_packet::TestPacket;
573 
574     const VLAN_ETHER_TYPES: [EtherType; 3] = [
575         ether_type::VLAN_TAGGED_FRAME,
576         ether_type::PROVIDER_BRIDGING,
577         ether_type::VLAN_DOUBLE_TAGGED_FRAME,
578     ];
579 
580     #[test]
clone_eq()581     fn clone_eq() {
582         let header = LaxPacketHeaders {
583             link: None,
584             vlan: None,
585             net: None,
586             transport: None,
587             stop_err: None,
588             payload: LaxPayloadSlice::Udp {
589                 payload: &[],
590                 incomplete: false,
591             },
592         };
593         assert_eq!(header.clone(), header);
594     }
595 
596     #[test]
debug()597     fn debug() {
598         use alloc::format;
599         let payload = LaxPayloadSlice::Udp {
600             payload: &[],
601             incomplete: false,
602         };
603         let header = LaxPacketHeaders {
604             link: None,
605             vlan: None,
606             net: None,
607             transport: None,
608             payload: payload.clone(),
609             stop_err: None,
610         };
611         assert_eq!(
612             format!("{:?}", header),
613             format!(
614                 "LaxPacketHeaders {{ link: {:?}, vlan: {:?}, net: {:?}, transport: {:?}, payload: {:?}, stop_err: {:?} }}",
615                 header.link, header.vlan, header.net, header.transport, payload, header.stop_err
616             )
617         );
618     }
619 
620     #[test]
from_x_slice()621     fn from_x_slice() {
622         // no eth
623         from_x_slice_vlan_variants(&TestPacket {
624             link: None,
625             vlan: None,
626             net: None,
627             transport: None,
628         });
629 
630         // eth
631         {
632             let eth = Ethernet2Header {
633                 source: [1, 2, 3, 4, 5, 6],
634                 destination: [1, 2, 3, 4, 5, 6],
635                 ether_type: 0.into(),
636             };
637             let test = TestPacket {
638                 link: Some(LinkHeader::Ethernet2(eth.clone())),
639                 vlan: None,
640                 net: None,
641                 transport: None,
642             };
643 
644             // ok ethernet header (with unknown next)
645             from_x_slice_vlan_variants(&test);
646 
647             // eth len error
648             {
649                 let data = test.to_vec(&[]);
650                 for len in 0..data.len() {
651                     assert_test_result(&test, &[], &data[..len], None, None);
652                 }
653             }
654         }
655 
656         // unknown ether_type
657         {
658             let payload = [1, 2, 3, 4];
659             let actual = LaxPacketHeaders::from_ether_type(0.into(), &payload);
660             assert_eq!(None, actual.link);
661             assert_eq!(None, actual.vlan);
662             assert_eq!(None, actual.net);
663             assert_eq!(None, actual.transport);
664             assert_eq!(
665                 actual.payload,
666                 LaxPayloadSlice::Ether(EtherPayloadSlice {
667                     ether_type: 0.into(),
668                     payload: &payload
669                 })
670             );
671             assert_eq!(None, actual.stop_err);
672         }
673     }
674 
from_x_slice_vlan_variants(base: &TestPacket)675     fn from_x_slice_vlan_variants(base: &TestPacket) {
676         // none
677         from_x_slice_ip_variants(base);
678 
679         // single vlan header
680         {
681             let single = SingleVlanHeader {
682                 pcp: 1.try_into().unwrap(),
683                 drop_eligible_indicator: false,
684                 vlan_id: 2.try_into().unwrap(),
685                 ether_type: 3.into(),
686             };
687 
688             for vlan_ether_type in VLAN_ETHER_TYPES {
689                 let mut test = base.clone();
690                 test.set_ether_type(vlan_ether_type);
691                 test.vlan = Some(VlanHeader::Single(single.clone()));
692 
693                 // ok vlan header
694                 from_x_slice_ip_variants(&test);
695 
696                 // len error
697                 {
698                     let data = test.to_vec(&[]);
699                     for len in 0..single.header_len() {
700                         let base_len = test.len(&[]) - single.header_len();
701 
702                         let err = LenError {
703                             required_len: single.header_len(),
704                             len,
705                             len_source: LenSource::Slice,
706                             layer: Layer::VlanHeader,
707                             layer_start_offset: base_len,
708                         };
709                         assert_test_result(
710                             &test,
711                             &[],
712                             &data[..base_len + len],
713                             None,
714                             Some((SliceError::Len(err.clone()), Layer::VlanHeader)),
715                         );
716                     }
717                 }
718             }
719         }
720 
721         // double vlan header
722         for outer_vlan_ether_type in VLAN_ETHER_TYPES {
723             for inner_vlan_ether_type in VLAN_ETHER_TYPES {
724                 let double = DoubleVlanHeader {
725                     outer: SingleVlanHeader {
726                         pcp: 1.try_into().unwrap(),
727                         drop_eligible_indicator: false,
728                         vlan_id: 2.try_into().unwrap(),
729                         ether_type: inner_vlan_ether_type,
730                     },
731                     inner: SingleVlanHeader {
732                         pcp: 1.try_into().unwrap(),
733                         drop_eligible_indicator: false,
734                         vlan_id: 2.try_into().unwrap(),
735                         ether_type: 3.into(),
736                     },
737                 };
738                 let mut test = base.clone();
739                 test.set_ether_type(outer_vlan_ether_type);
740                 test.vlan = Some(VlanHeader::Double(double.clone()));
741 
742                 // ok double vlan header
743                 from_x_slice_ip_variants(&test);
744 
745                 // len error
746                 {
747                     let data = test.to_vec(&[]);
748                     for len in 0..SingleVlanHeader::LEN {
749                         let base_len = test.len(&[]) - SingleVlanHeader::LEN;
750 
751                         let err = LenError {
752                             required_len: SingleVlanHeader::LEN,
753                             len,
754                             len_source: LenSource::Slice,
755                             layer: Layer::VlanHeader,
756                             layer_start_offset: base_len,
757                         };
758                         assert_test_result(
759                             &test,
760                             &[],
761                             &data[..base_len + len],
762                             None,
763                             Some((SliceError::Len(err.clone()), Layer::VlanHeader)),
764                         );
765                     }
766                 }
767             }
768         }
769     }
770 
from_x_slice_ip_variants(base: &TestPacket)771     fn from_x_slice_ip_variants(base: &TestPacket) {
772         // none
773         from_x_slice_transport_variants(base);
774 
775         // ipv4
776         for fragmented in [false, true] {
777             let ipv4 = {
778                 let mut ipv4 =
779                     Ipv4Header::new(0, 1, 2.into(), [3, 4, 5, 6], [7, 8, 9, 10]).unwrap();
780                 ipv4.more_fragments = fragmented;
781                 ipv4
782             };
783 
784             {
785                 let mut test = base.clone();
786                 test.set_ether_type(ether_type::IPV4);
787                 test.net = Some(NetHeaders::Ipv4(ipv4.clone(), Default::default()));
788                 test.set_payload_len(0);
789 
790                 // ok ipv4
791                 from_x_slice_transport_variants(&test);
792 
793                 // ipv4 len error
794                 {
795                     let data = test.to_vec(&[]);
796                     for len in 0..ipv4.header_len() {
797                         let base_len = test.len(&[]) - ipv4.header_len();
798 
799                         let err = LenError {
800                             required_len: if len < 1 { 1 } else { ipv4.header_len() },
801                             len,
802                             len_source: LenSource::Slice,
803                             layer: if len < 1 {
804                                 Layer::IpHeader
805                             } else {
806                                 Layer::Ipv4Header
807                             },
808                             layer_start_offset: base_len,
809                         };
810 
811                         assert_test_result(
812                             &test,
813                             &[],
814                             &data[..base_len + len],
815                             Some(err::ip::LaxHeaderSliceError::Len(err.clone())),
816                             Some((SliceError::Len(err.clone()), Layer::IpHeader)),
817                         );
818                     }
819                 }
820 
821                 // ipv4 content error (ihl length too small)
822                 {
823                     use err::ip::HeaderError::*;
824 
825                     let mut data = test.to_vec(&[]);
826                     let ipv4_offset = data.len() - ipv4.header_len();
827 
828                     // set the ihl to 0 to trigger a content error
829                     data[ipv4_offset] = 0b1111_0000 & data[ipv4_offset];
830 
831                     assert_test_result(
832                         &test,
833                         &[],
834                         &data,
835                         Some(err::ip::LaxHeaderSliceError::Content(
836                             Ipv4HeaderLengthSmallerThanHeader { ihl: 0 },
837                         )),
838                         Some((
839                             SliceError::Ip(Ipv4HeaderLengthSmallerThanHeader { ihl: 0 }),
840                             Layer::IpHeader,
841                         )),
842                     );
843                 }
844 
845                 // ipv 4total length too small (does not change the output)
846                 {
847                     let mut data = test.to_vec(&[]);
848                     let ipv4_offset = data.len() - ipv4.header_len();
849 
850                     // set the total length to 0 to trigger a content error
851                     data[ipv4_offset + 2] = 0;
852                     data[ipv4_offset + 3] = 0;
853 
854                     let mut mod_test = test.clone();
855                     mod_test.net = Some({
856                         let (h, e) = test.net.as_ref().map(|v| v.ipv4_ref()).flatten().unwrap();
857                         let mut ipv4 = h.clone();
858                         ipv4.total_len = 0;
859                         NetHeaders::Ipv4(ipv4, e.clone())
860                     });
861 
862                     assert_test_result(&mod_test, &[], &data, None, None);
863                 }
864             }
865 
866             // ipv4 extension content error
867             {
868                 let auth = IpAuthHeader::new(0.into(), 1, 2, &[]).unwrap();
869 
870                 let mut test = base.clone();
871                 test.set_ether_type(ether_type::IPV4);
872                 test.net = Some(NetHeaders::Ipv4(
873                     {
874                         let mut ipv4 = ipv4.clone();
875                         ipv4.protocol = ip_number::AUTH;
876                         ipv4
877                     },
878                     Ipv4Extensions {
879                         auth: Some(auth.clone()),
880                     },
881                 ));
882                 test.set_payload_len(0);
883 
884                 // ok ipv4 & extension
885                 from_x_slice_transport_variants(&test);
886 
887                 // ipv4 extension len error
888                 for len in 0..auth.header_len() {
889                     // set payload length
890                     let mut test = test.clone();
891                     test.set_payload_le_from_ip_on(
892                         -1 * (auth.header_len() as isize) + (len as isize),
893                     );
894 
895                     let data = test.to_vec(&[]);
896                     let base_len = test.len(&[]) - auth.header_len();
897 
898                     let err = LenError {
899                         required_len: auth.header_len(),
900                         len,
901                         len_source: LenSource::Ipv4HeaderTotalLen,
902                         layer: Layer::IpAuthHeader,
903                         layer_start_offset: base_len,
904                     };
905 
906                     assert_test_result(
907                         &test,
908                         &[],
909                         &data,
910                         None,
911                         Some((SliceError::Len(err.clone()), Layer::IpAuthHeader)),
912                     );
913                 }
914 
915                 // ipv4 extension content error
916                 {
917                     let mut data = test.to_vec(&[]);
918                     let auth_offset = data.len() - auth.header_len();
919 
920                     // set the icv len too smaller then allowed
921                     data[auth_offset + 1] = 0;
922 
923                     // expect an error
924                     assert_test_result(
925                         &test,
926                         &[],
927                         &data,
928                         None,
929                         Some((
930                             SliceError::Ipv4Exts(err::ip_auth::HeaderError::ZeroPayloadLen),
931                             Layer::IpAuthHeader,
932                         )),
933                     );
934                 }
935             }
936         }
937 
938         // ipv6
939         {
940             let ipv6 = Ipv6Header {
941                 traffic_class: 0,
942                 flow_label: 1.try_into().unwrap(),
943                 payload_length: 2,
944                 next_header: 3.into(),
945                 hop_limit: 4,
946                 source: [0; 16],
947                 destination: [0; 16],
948             };
949 
950             // ipv6 header only
951             {
952                 let mut test = base.clone();
953                 test.set_ether_type(ether_type::IPV6);
954                 test.net = Some(NetHeaders::Ipv6(ipv6.clone(), Default::default()));
955                 test.set_payload_len(0);
956 
957                 // ok ipv6
958                 from_x_slice_transport_variants(&test);
959 
960                 // header len ipv6
961                 {
962                     let data = test.to_vec(&[]);
963                     for len in 0..ipv6.header_len() {
964                         let base_len = test.len(&[]) - ipv6.header_len();
965 
966                         let err = err::LenError {
967                             required_len: if len < 1 { 1 } else { ipv6.header_len() },
968                             len,
969                             len_source: LenSource::Slice,
970                             layer: if len < 1 {
971                                 Layer::IpHeader
972                             } else {
973                                 Layer::Ipv6Header
974                             },
975                             layer_start_offset: base_len,
976                         };
977 
978                         assert_test_result(
979                             &test,
980                             &[],
981                             &data[..base_len + len],
982                             Some(err::ip::LaxHeaderSliceError::Len(err.clone())),
983                             Some((
984                                 SliceError::Len({
985                                     if len < 1 {
986                                         let mut err = err.clone();
987                                         err.required_len = 1;
988                                         err.layer = Layer::IpHeader;
989                                         err
990                                     } else {
991                                         err.clone()
992                                     }
993                                 }),
994                                 Layer::IpHeader,
995                             )),
996                         );
997                     }
998                 }
999 
1000                 // content error ipv6
1001                 {
1002                     use err::ip::{HeaderError::*, LaxHeaderSliceError::Content};
1003 
1004                     let mut data = test.to_vec(&[]);
1005 
1006                     // inject an invalid ip version
1007                     let base_len = data.len() - ipv6.header_len();
1008                     data[base_len] = data[base_len] & 0b0000_1111;
1009 
1010                     assert_test_result(
1011                         &test,
1012                         &[],
1013                         &data,
1014                         Some(Content(UnsupportedIpVersion { version_number: 0 })),
1015                         Some((
1016                             SliceError::Ip(UnsupportedIpVersion { version_number: 0 }),
1017                             Layer::IpHeader,
1018                         )),
1019                     );
1020                 }
1021             }
1022 
1023             // ipv6 + extension
1024             for fragment in [false, true] {
1025                 let auth = IpAuthHeader::new(ip_number::GGP, 1, 2, &[]).unwrap();
1026                 let frag = Ipv6FragmentHeader {
1027                     next_header: ip_number::AUTH,
1028                     fragment_offset: 0.try_into().unwrap(),
1029                     more_fragments: fragment,
1030                     identification: 3,
1031                 };
1032 
1033                 let mut test = base.clone();
1034                 test.set_ether_type(ether_type::IPV6);
1035                 test.net = Some(NetHeaders::Ipv6(
1036                     {
1037                         let mut ipv6 = ipv6.clone();
1038                         ipv6.next_header = ip_number::IPV6_FRAG;
1039                         ipv6
1040                     },
1041                     {
1042                         let mut exts: Ipv6Extensions = Default::default();
1043                         exts.fragment = Some(frag.clone());
1044                         exts.auth = Some(auth.clone());
1045                         exts
1046                     },
1047                 ));
1048                 test.set_payload_len(0);
1049 
1050                 // ok ipv6 & extensions
1051                 from_x_slice_transport_variants(&test);
1052 
1053                 // ipv6 extension len error
1054                 for len in 0..auth.header_len() {
1055                     // set payload length
1056                     let mut test = test.clone();
1057                     test.set_payload_le_from_ip_on(
1058                         -1 * (auth.header_len() as isize) + (len as isize),
1059                     );
1060 
1061                     let data = test.to_vec(&[]);
1062                     let base_len = test.len(&[]) - auth.header_len();
1063 
1064                     let err = LenError {
1065                         required_len: auth.header_len(),
1066                         len,
1067                         len_source: LenSource::Ipv6HeaderPayloadLen,
1068                         layer: Layer::IpAuthHeader,
1069                         layer_start_offset: base_len,
1070                     };
1071                     assert_test_result(
1072                         &test,
1073                         &[],
1074                         &data[..base_len + len],
1075                         None,
1076                         Some((SliceError::Len(err.clone()), Layer::IpAuthHeader)),
1077                     );
1078                 }
1079 
1080                 // ipv6 extension content error (auth)
1081                 {
1082                     let mut data = test.to_vec(&[]);
1083                     let auth_offset = data.len() - auth.header_len();
1084                     // set the icv len too smaller then allowed
1085                     data[auth_offset + 1] = 0;
1086 
1087                     assert_test_result(
1088                         &test,
1089                         &[],
1090                         &data,
1091                         None,
1092                         Some((
1093                             SliceError::Ipv6Exts(err::ipv6_exts::HeaderError::IpAuth(
1094                                 err::ip_auth::HeaderError::ZeroPayloadLen,
1095                             )),
1096                             Layer::IpAuthHeader,
1097                         )),
1098                     );
1099                 }
1100 
1101                 // ipv6 extension content error (hop by hop not at start)
1102                 {
1103                     let mut data = test.to_vec(&[]);
1104                     let auth_offset = data.len() - auth.header_len();
1105 
1106                     // set the next header to be a hop-by-hop header to trigger a "not at start error"
1107                     data[auth_offset] = 0;
1108 
1109                     assert_test_result(
1110                         &test,
1111                         &[],
1112                         &data,
1113                         None,
1114                         Some((
1115                             SliceError::Ipv6Exts(err::ipv6_exts::HeaderError::HopByHopNotAtStart),
1116                             Layer::Ipv6HopByHopHeader,
1117                         )),
1118                     );
1119                 }
1120             }
1121         }
1122     }
1123 
from_x_slice_transport_variants(base: &TestPacket)1124     fn from_x_slice_transport_variants(base: &TestPacket) {
1125         // none
1126         from_x_slice_assert_ok(base);
1127 
1128         // transport can only be set if ip is present
1129         if let Some(ip) = &base.net {
1130             // udp
1131             {
1132                 let udp = UdpHeader {
1133                     source_port: 1,
1134                     destination_port: 2,
1135                     length: 3,
1136                     checksum: 4,
1137                 };
1138                 let mut test = base.clone();
1139                 test.net = Some({
1140                     let mut ip = match ip {
1141                         NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1142                         NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1143                     };
1144                     ip.set_next_headers(ip_number::UDP);
1145                     ip.into()
1146                 });
1147                 test.transport = Some(TransportHeader::Udp(udp.clone()));
1148                 test.set_payload_len(0);
1149 
1150                 // ok decode
1151                 from_x_slice_assert_ok(&test);
1152 
1153                 // length error
1154                 if false == test.is_ip_payload_fragmented() {
1155                     for len in 0..udp.header_len() {
1156                         // build new test packet
1157                         let mut test = test.clone();
1158 
1159                         // set payload length
1160                         test.set_payload_le_from_ip_on(len as isize);
1161 
1162                         // generate data
1163                         let data = test.to_vec(&[]);
1164 
1165                         let base_len = test.len(&[]) - udp.header_len();
1166                         let err = LenError {
1167                             required_len: udp.header_len(),
1168                             len,
1169                             len_source: match test.net.as_ref().unwrap() {
1170                                 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1171                                 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1172                             },
1173                             layer: Layer::UdpHeader,
1174                             layer_start_offset: base_len,
1175                         };
1176                         assert_test_result(
1177                             &test,
1178                             &[],
1179                             &data[..base_len + len],
1180                             None,
1181                             Some((SliceError::Len(err.clone()), Layer::UdpHeader)),
1182                         );
1183                     }
1184                 }
1185             }
1186 
1187             // tcp
1188             {
1189                 let tcp = TcpHeader::new(1, 2, 3, 4);
1190                 let mut test = base.clone();
1191                 test.net = Some({
1192                     let mut ip = match ip {
1193                         NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1194                         NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1195                     };
1196                     ip.set_next_headers(ip_number::TCP);
1197                     ip.into()
1198                 });
1199                 test.transport = Some(TransportHeader::Tcp(tcp.clone()));
1200                 test.set_payload_len(0);
1201 
1202                 // ok decode
1203                 from_x_slice_assert_ok(&test);
1204 
1205                 // error can only occur if ip does not fragment the packet
1206                 if false == test.is_ip_payload_fragmented() {
1207                     // length error
1208                     {
1209                         for len in 0..(tcp.header_len() as usize) {
1210                             // set payload length
1211                             let mut test = test.clone();
1212                             test.set_payload_le_from_ip_on(len as isize);
1213 
1214                             let data = test.to_vec(&[]);
1215                             let base_len = test.len(&[]) - (tcp.header_len() as usize);
1216 
1217                             let err = LenError {
1218                                 required_len: tcp.header_len() as usize,
1219                                 len,
1220                                 len_source: match test.net.as_ref().unwrap() {
1221                                     NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1222                                     NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1223                                 },
1224                                 layer: Layer::TcpHeader,
1225                                 layer_start_offset: base_len,
1226                             };
1227                             assert_test_result(
1228                                 &test,
1229                                 &[],
1230                                 &data[..base_len + len],
1231                                 None,
1232                                 Some((SliceError::Len(err.clone()), Layer::TcpHeader)),
1233                             );
1234                         }
1235                     }
1236 
1237                     // content error
1238                     {
1239                         let mut data = test.to_vec(&[]);
1240                         let base_len = test.len(&[]) - (tcp.header_len() as usize);
1241 
1242                         // set data offset to 0 to trigger an error
1243                         data[base_len + 12] = data[base_len + 12] & 0b0000_1111;
1244 
1245                         let err = err::tcp::HeaderError::DataOffsetTooSmall { data_offset: 0 };
1246                         assert_test_result(
1247                             &test,
1248                             &[],
1249                             &data,
1250                             None,
1251                             Some((SliceError::Tcp(err.clone()), Layer::TcpHeader)),
1252                         );
1253                     }
1254                 }
1255             }
1256 
1257             // icmpv4
1258             {
1259                 let icmpv4 =
1260                     Icmpv4Header::new(Icmpv4Type::EchoReply(IcmpEchoHeader { id: 1, seq: 2 }));
1261                 let mut test = base.clone();
1262                 test.net = Some({
1263                     let mut ip = match ip {
1264                         NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1265                         NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1266                     };
1267                     ip.set_next_headers(ip_number::ICMP);
1268                     ip.into()
1269                 });
1270                 test.transport = Some(TransportHeader::Icmpv4(icmpv4.clone()));
1271                 test.set_payload_len(0);
1272 
1273                 // ok decode
1274                 from_x_slice_assert_ok(&test);
1275 
1276                 // length error
1277                 if false == test.is_ip_payload_fragmented() {
1278                     for len in 0..icmpv4.header_len() {
1279                         // set payload length
1280                         let mut test = test.clone();
1281                         test.set_payload_le_from_ip_on(len as isize);
1282 
1283                         let data = test.to_vec(&[]);
1284                         let base_len = test.len(&[]) - icmpv4.header_len();
1285 
1286                         let err = LenError {
1287                             required_len: icmpv4.header_len(),
1288                             len,
1289                             len_source: match test.net.as_ref().unwrap() {
1290                                 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1291                                 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1292                             },
1293                             layer: Layer::Icmpv4,
1294                             layer_start_offset: base_len,
1295                         };
1296                         assert_test_result(
1297                             &test,
1298                             &[],
1299                             &data[..base_len + len],
1300                             None,
1301                             Some((SliceError::Len(err.clone()), Layer::Icmpv4)),
1302                         );
1303                     }
1304                 }
1305             }
1306 
1307             // icmpv6
1308             {
1309                 let icmpv6 =
1310                     Icmpv6Header::new(Icmpv6Type::EchoReply(IcmpEchoHeader { id: 1, seq: 2 }));
1311                 let mut test = base.clone();
1312                 test.net = Some({
1313                     let mut ip = match ip {
1314                         NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1315                         NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1316                     };
1317                     ip.set_next_headers(ip_number::IPV6_ICMP);
1318                     ip.into()
1319                 });
1320                 test.transport = Some(TransportHeader::Icmpv6(icmpv6.clone()));
1321                 test.set_payload_len(0);
1322 
1323                 // ok decode
1324                 from_x_slice_assert_ok(&test);
1325 
1326                 // length error
1327                 if false == test.is_ip_payload_fragmented() {
1328                     for len in 0..icmpv6.header_len() {
1329                         // set payload length
1330                         let mut test = test.clone();
1331                         test.set_payload_le_from_ip_on(len as isize);
1332 
1333                         let data = test.to_vec(&[]);
1334                         let base_len = test.len(&[]) - icmpv6.header_len();
1335 
1336                         let err = LenError {
1337                             required_len: icmpv6.header_len(),
1338                             len,
1339                             len_source: match test.net.as_ref().unwrap() {
1340                                 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1341                                 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1342                             },
1343                             layer: Layer::Icmpv6,
1344                             layer_start_offset: base_len,
1345                         };
1346                         assert_test_result(
1347                             &test,
1348                             &[],
1349                             &data[..base_len + len],
1350                             None,
1351                             Some((SliceError::Len(err.clone()), Layer::Icmpv6)),
1352                         );
1353                     }
1354                 }
1355             }
1356         }
1357     }
1358 
from_x_slice_assert_ok(test_base: &TestPacket)1359     fn from_x_slice_assert_ok(test_base: &TestPacket) {
1360         // setup payload
1361         let payload = [1, 2, 3, 4];
1362 
1363         // set length fields in ip headers
1364         let test = {
1365             let mut test = test_base.clone();
1366             test.set_payload_len(payload.len());
1367             test
1368         };
1369 
1370         // write data
1371         let data = test.to_vec(&payload);
1372         assert_test_result(&test, &payload, &data, None, None);
1373     }
1374 
1375     /// Check that the given output & errors (if present) are generated based on the given
1376     /// input.
assert_test_result( test: &TestPacket, expected_payload: &[u8], data: &[u8], expected_ip_err: Option<err::ip::LaxHeaderSliceError>, expected_stop_err: Option<(SliceError, Layer)>, )1377     fn assert_test_result(
1378         test: &TestPacket,
1379         expected_payload: &[u8],
1380         data: &[u8],
1381         expected_ip_err: Option<err::ip::LaxHeaderSliceError>,
1382         expected_stop_err: Option<(SliceError, Layer)>,
1383     ) {
1384         fn compare_vlan(test: &TestPacket, data: &[u8], actual: &LaxPacketHeaders) {
1385             let vlan_offset = if let Some(e) = test.link.as_ref() {
1386                 e.header_len()
1387             } else {
1388                 0
1389             };
1390             match test.vlan.as_ref() {
1391                 Some(VlanHeader::Double(d)) => {
1392                     if data.len() >= vlan_offset + DoubleVlanHeader::LEN {
1393                         assert_eq!(test.vlan, actual.vlan);
1394                     } else if data.len() >= vlan_offset + SingleVlanHeader::LEN {
1395                         assert_eq!(Some(VlanHeader::Single(d.outer.clone())), actual.vlan);
1396                     } else {
1397                         assert_eq!(None, actual.vlan);
1398                     }
1399                 }
1400                 Some(VlanHeader::Single(s)) => {
1401                     if data.len() >= vlan_offset + SingleVlanHeader::LEN {
1402                         assert_eq!(Some(VlanHeader::Single(s.clone())), actual.vlan);
1403                     } else {
1404                         assert_eq!(None, actual.vlan);
1405                     }
1406                 }
1407                 None => {
1408                     assert_eq!(None, actual.vlan);
1409                 }
1410             }
1411         }
1412 
1413         fn compare_ip_header_only(test: &TestPacket, actual: &LaxPacketHeaders) {
1414             assert_eq!(
1415                 test.net.as_ref().map(|s| -> NetHeaders {
1416                     match s {
1417                         NetHeaders::Ipv4(h, _) => NetHeaders::Ipv4(h.clone(), Default::default()),
1418                         NetHeaders::Ipv6(h, _) => NetHeaders::Ipv6(h.clone(), Default::default()),
1419                     }
1420                 }),
1421                 actual.net.as_ref().map(|s| -> NetHeaders {
1422                     match s {
1423                         NetHeaders::Ipv4(h, _) => NetHeaders::Ipv4(h.clone(), Default::default()),
1424                         NetHeaders::Ipv6(h, _) => NetHeaders::Ipv6(h.clone(), Default::default()),
1425                     }
1426                 })
1427             );
1428         }
1429 
1430         fn compare_transport(
1431             test: &TestPacket,
1432             is_fragmented: bool,
1433             expected_payload: &[u8],
1434             actual: &LaxPacketHeaders,
1435         ) {
1436             if is_fragmented {
1437                 assert_eq!(actual.transport, None);
1438             } else {
1439                 use TransportHeader as H;
1440                 match &actual.transport {
1441                     Some(H::Icmpv4(icmpv4)) => {
1442                         assert_eq!(&test.transport, &Some(H::Icmpv4(icmpv4.clone())));
1443                         assert_eq!(
1444                             actual.payload,
1445                             LaxPayloadSlice::Icmpv4 {
1446                                 payload: expected_payload,
1447                                 incomplete: false
1448                             }
1449                         );
1450                     }
1451                     Some(H::Icmpv6(icmpv6)) => {
1452                         assert_eq!(&test.transport, &Some(H::Icmpv6(icmpv6.clone())));
1453                         assert_eq!(
1454                             actual.payload,
1455                             LaxPayloadSlice::Icmpv6 {
1456                                 payload: expected_payload,
1457                                 incomplete: false
1458                             }
1459                         );
1460                     }
1461                     Some(H::Udp(s)) => {
1462                         assert_eq!(&test.transport, &Some(H::Udp(s.clone())));
1463                         assert_eq!(
1464                             actual.payload,
1465                             LaxPayloadSlice::Udp {
1466                                 payload: expected_payload,
1467                                 incomplete: false
1468                             }
1469                         );
1470                     }
1471                     Some(H::Tcp(s)) => {
1472                         assert_eq!(&test.transport, &Some(H::Tcp(s.clone())));
1473                         assert_eq!(
1474                             actual.payload,
1475                             LaxPayloadSlice::Tcp {
1476                                 payload: expected_payload,
1477                                 incomplete: false
1478                             }
1479                         );
1480                     }
1481                     None => {
1482                         assert_eq!(&test.transport, &None);
1483                     }
1484                 }
1485             }
1486         }
1487 
1488         // from_ethernet_slice
1489         if test.link.is_some() {
1490             if data.len() < Ethernet2Header::LEN {
1491                 assert_eq!(
1492                     LenError {
1493                         required_len: Ethernet2Header::LEN,
1494                         len: data.len(),
1495                         len_source: LenSource::Slice,
1496                         layer: Layer::Ethernet2Header,
1497                         layer_start_offset: 0
1498                     },
1499                     LaxPacketHeaders::from_ethernet(&data).unwrap_err()
1500                 );
1501             } else {
1502                 let actual = LaxPacketHeaders::from_ethernet(&data).unwrap();
1503                 assert_eq!(actual.stop_err, expected_stop_err);
1504                 match expected_stop_err.as_ref().map(|v| v.1) {
1505                     None => {
1506                         assert_eq!(test.link, actual.link);
1507                         compare_vlan(test, data, &actual);
1508                         assert_eq!(test.net, actual.net);
1509                         compare_transport(
1510                             test,
1511                             test.is_ip_payload_fragmented(),
1512                             expected_payload,
1513                             &actual,
1514                         );
1515                     }
1516                     Some(Layer::VlanHeader) => {
1517                         assert_eq!(test.link, actual.link);
1518                         compare_vlan(test, data, &actual);
1519                         assert_eq!(None, actual.net);
1520                         assert_eq!(None, actual.transport);
1521                         assert!(matches!(actual.payload, LaxPayloadSlice::Ether(_)));
1522                     }
1523                     Some(Layer::Ipv6Header) | Some(Layer::Ipv4Header) | Some(Layer::IpHeader) => {
1524                         assert_eq!(test.link, actual.link);
1525                         compare_vlan(test, data, &actual);
1526                         assert_eq!(None, actual.net);
1527                         assert_eq!(None, actual.transport);
1528                         assert!(matches!(actual.payload, LaxPayloadSlice::Ether(_)));
1529                     }
1530                     Some(Layer::IpAuthHeader)
1531                     | Some(Layer::Ipv6ExtHeader)
1532                     | Some(Layer::Ipv6HopByHopHeader)
1533                     | Some(Layer::Ipv6DestOptionsHeader)
1534                     | Some(Layer::Ipv6RouteHeader)
1535                     | Some(Layer::Ipv6FragHeader) => {
1536                         assert_eq!(test.link, actual.link);
1537                         compare_vlan(test, data, &actual);
1538                         compare_ip_header_only(test, &actual);
1539                         assert_eq!(None, actual.transport);
1540                         assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
1541                     }
1542                     Some(Layer::TcpHeader)
1543                     | Some(Layer::UdpHeader)
1544                     | Some(Layer::Icmpv4)
1545                     | Some(Layer::Icmpv6) => {
1546                         assert_eq!(test.link, actual.link);
1547                         compare_vlan(test, data, &actual);
1548                         assert_eq!(test.net, actual.net);
1549                         assert_eq!(None, actual.transport);
1550                         assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
1551                     }
1552                     _ => unreachable!("error in an unexpected layer"),
1553                 }
1554             }
1555         }
1556         // from_ether_type (vlan at start)
1557         if test.link.is_none() && test.vlan.is_some() {
1558             for ether_type in VLAN_ETHER_TYPES {
1559                 let actual = LaxPacketHeaders::from_ether_type(ether_type, data);
1560                 assert_eq!(actual.stop_err, expected_stop_err);
1561                 compare_vlan(test, data, &actual);
1562                 match expected_stop_err.as_ref().map(|v| v.1) {
1563                     None => {
1564                         assert_eq!(test.net, actual.net);
1565                         compare_transport(
1566                             test,
1567                             test.is_ip_payload_fragmented(),
1568                             expected_payload,
1569                             &actual,
1570                         );
1571                     }
1572                     Some(Layer::VlanHeader) => {
1573                         assert_eq!(None, actual.net);
1574                         assert_eq!(None, actual.transport);
1575                         assert!(matches!(actual.payload, LaxPayloadSlice::Ether(_)));
1576                     }
1577                     Some(Layer::Ipv6Header) | Some(Layer::Ipv4Header) | Some(Layer::IpHeader) => {
1578                         assert_eq!(None, actual.net);
1579                         assert_eq!(None, actual.transport);
1580                         assert!(matches!(actual.payload, LaxPayloadSlice::Ether(_)));
1581                     }
1582                     Some(Layer::IpAuthHeader)
1583                     | Some(Layer::Ipv6ExtHeader)
1584                     | Some(Layer::Ipv6HopByHopHeader)
1585                     | Some(Layer::Ipv6DestOptionsHeader)
1586                     | Some(Layer::Ipv6RouteHeader)
1587                     | Some(Layer::Ipv6FragHeader) => {
1588                         compare_ip_header_only(test, &actual);
1589                         assert_eq!(None, actual.transport);
1590                         assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
1591                     }
1592                     Some(Layer::TcpHeader)
1593                     | Some(Layer::UdpHeader)
1594                     | Some(Layer::Icmpv4)
1595                     | Some(Layer::Icmpv6) => {
1596                         assert_eq!(test.net, actual.net);
1597                         assert_eq!(None, actual.transport);
1598                         assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
1599                     }
1600                     _ => unreachable!("error in an unexpected layer"),
1601                 }
1602             }
1603         }
1604         // from_ether_type (ip at start)
1605         if test.link.is_none() && test.vlan.is_none() {
1606             if let Some(ip) = &test.net {
1607                 let ether_type = match ip {
1608                     NetHeaders::Ipv4(_, _) => ether_type::IPV4,
1609                     NetHeaders::Ipv6(_, _) => ether_type::IPV6,
1610                 };
1611                 let actual = LaxPacketHeaders::from_ether_type(ether_type, &data);
1612                 assert_eq!(actual.stop_err, expected_stop_err);
1613                 assert_eq!(None, actual.link);
1614                 assert_eq!(test.vlan, None);
1615                 match expected_stop_err.as_ref().map(|v| v.1) {
1616                     None => {
1617                         assert_eq!(test.net, actual.net);
1618                         compare_transport(
1619                             test,
1620                             test.is_ip_payload_fragmented(),
1621                             expected_payload,
1622                             &actual,
1623                         );
1624                     }
1625                     Some(Layer::Ipv6Header) | Some(Layer::Ipv4Header) | Some(Layer::IpHeader) => {
1626                         assert_eq!(None, actual.net);
1627                         assert_eq!(None, actual.transport);
1628                         assert_eq!(
1629                             LaxPayloadSlice::Ether(EtherPayloadSlice {
1630                                 ether_type,
1631                                 payload: data
1632                             }),
1633                             actual.payload
1634                         );
1635                     }
1636                     Some(Layer::IpAuthHeader)
1637                     | Some(Layer::Ipv6ExtHeader)
1638                     | Some(Layer::Ipv6HopByHopHeader)
1639                     | Some(Layer::Ipv6DestOptionsHeader)
1640                     | Some(Layer::Ipv6RouteHeader)
1641                     | Some(Layer::Ipv6FragHeader) => {
1642                         compare_ip_header_only(test, &actual);
1643                         assert_eq!(None, actual.transport);
1644                         assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
1645                     }
1646                     Some(Layer::TcpHeader)
1647                     | Some(Layer::UdpHeader)
1648                     | Some(Layer::Icmpv4)
1649                     | Some(Layer::Icmpv6) => {
1650                         assert_eq!(test.net, actual.net);
1651                         assert_eq!(None, actual.transport);
1652                         assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
1653                     }
1654                     _ => unreachable!("error in an unexpected layer"),
1655                 }
1656             }
1657         }
1658         // from_ip_slice
1659         if test.link.is_none() && test.vlan.is_none() && test.net.is_some() {
1660             if let Some(err) = expected_ip_err {
1661                 assert_eq!(err, LaxPacketHeaders::from_ip(&data).unwrap_err());
1662             } else {
1663                 let actual = LaxPacketHeaders::from_ip(&data).unwrap();
1664                 assert_eq!(actual.stop_err, expected_stop_err);
1665                 assert_eq!(actual.link, None);
1666                 assert_eq!(test.vlan, None);
1667                 match expected_stop_err.as_ref().map(|v| v.1) {
1668                     None => {
1669                         assert_eq!(test.net, actual.net);
1670                         compare_transport(
1671                             test,
1672                             test.is_ip_payload_fragmented(),
1673                             expected_payload,
1674                             &actual,
1675                         );
1676                     }
1677                     Some(Layer::IpAuthHeader)
1678                     | Some(Layer::Ipv6ExtHeader)
1679                     | Some(Layer::Ipv6HopByHopHeader)
1680                     | Some(Layer::Ipv6DestOptionsHeader)
1681                     | Some(Layer::Ipv6RouteHeader)
1682                     | Some(Layer::Ipv6FragHeader) => {
1683                         compare_ip_header_only(test, &actual);
1684                         assert_eq!(None, actual.transport);
1685                         assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
1686                     }
1687                     Some(Layer::TcpHeader)
1688                     | Some(Layer::UdpHeader)
1689                     | Some(Layer::Icmpv4)
1690                     | Some(Layer::Icmpv6) => {
1691                         assert_eq!(test.net, actual.net);
1692                         assert_eq!(None, actual.transport);
1693                         assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
1694                     }
1695                     _ => unreachable!("error in an unexpected layer"),
1696                 }
1697             }
1698         }
1699     }
1700 }
1701