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