Thanks to visit codestin.com
Credit goes to docs.rs

etherparse/
lax_sliced_packet.rs

1use arrayvec::ArrayVec;
2
3use crate::{err::Layer, *};
4
5/// Packet slice split into multiple slices containing
6/// the different headers & payload.
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub struct LaxSlicedPacket<'a> {
9    /// Ethernet II header if present.
10    pub link: Option<LinkSlice<'a>>,
11
12    /// Link extensions (VLAN & MAC Sec headers).
13    pub link_exts: ArrayVec<LaxLinkExtSlice<'a>, { LaxSlicedPacket::LINK_EXTS_CAP }>,
14
15    /// IPv4 or IPv6 header, IP extension headers & payload if present.
16    pub net: Option<LaxNetSlice<'a>>,
17
18    /// TCP or UDP header & payload if present.
19    pub transport: Option<TransportSlice<'a>>,
20
21    /// Error that stopped the parsing and the layer on which the stop occurred.
22    pub stop_err: Option<(err::packet::SliceError, Layer)>,
23}
24
25impl<'a> LaxSlicedPacket<'a> {
26    /// Maximum supported number of link extensions.
27    pub const LINK_EXTS_CAP: usize = 3;
28
29    /// Separates a network packet slice into different slices containing the
30    /// headers from the ethernet header downwards with lax length checks and
31    /// non-terminating errors.
32    ///
33    /// # Example
34    ///
35    /// Basic usage:
36    ///
37    ///```
38    /// # use etherparse::{Ethernet2Header, PacketBuilder};
39    /// # let builder = PacketBuilder::
40    /// #    ethernet2([1,2,3,4,5,6],     //source mac
41    /// #               [7,8,9,10,11,12]) //destination mac
42    /// #    .ipv4([192,168,1,1], //source ip
43    /// #          [192,168,1,2], //destination ip
44    /// #          20)            //time to life
45    /// #    .udp(21,    //source port
46    /// #         1234); //destination port
47    /// # // payload of the udp packet
48    /// # let payload = [1,2,3,4,5,6,7,8];
49    /// # // get some memory to store the serialized data
50    /// # let mut packet = Vec::<u8>::with_capacity(
51    /// #     builder.size(payload.len())
52    /// # );
53    /// # builder.write(&mut packet, &payload).unwrap();
54    /// #
55    /// use etherparse::{ether_type, LaxSlicedPacket, LenSource};
56    ///
57    /// match LaxSlicedPacket::from_ethernet(&packet) {
58    ///     Err(value) => {
59    ///         // An error is returned in case the ethernet II header could
60    ///         // not be parsed (other errors are stored in the "stop_err" field)
61    ///         println!("Err {:?}", value)
62    ///     },
63    ///     Ok(value) => {
64    ///         if let Some((stop_err, error_layer)) = value.stop_err.as_ref() {
65    ///             // error was encountered after parsing the ethernet 2 header
66    ///             println!("Error on layer {}: {:?}", error_layer, stop_err);
67    ///         }
68    ///
69    ///         // parts that could be parsed without error
70    ///         println!("link: {:?}", value.link);
71    ///         println!("link_exts: {:?}", value.link_exts); // vlan & macsec
72    ///
73    ///         // net (ip or arp)
74    ///         println!("net: {:?}", value.net);
75    ///         if let Some(ip_payload) = value.net.as_ref().map(|net| net.ip_payload_ref()).flatten() {
76    ///             // the ip payload len_source field can be used to check
77    ///             // if the slice length was used as a fallback value
78    ///             if ip_payload.len_source == LenSource::Slice {
79    ///                 println!("  Used slice length as fallback to identify the IP payload");
80    ///             } else {
81    ///                 println!("  IP payload could correctly be identified via the length field in the header");
82    ///             }
83    ///         }
84    ///
85    ///         // transport (udp or tcp)
86    ///         println!("transport: {:?}", value.transport);
87    ///     }
88    /// };
89    ///
90    /// ```
91    pub fn from_ethernet(slice: &'a [u8]) -> Result<LaxSlicedPacket<'a>, err::LenError> {
92        LaxSlicedPacketCursor::parse_from_ethernet2(slice)
93    }
94
95    /// Separates a network packet slice into different slices containing the headers using
96    /// the given `ether_type` number to identify the first header with lax length
97    /// checks and non-terminating errors.
98    ///
99    /// The result is returned as a [`LaxSlicedPacket`] struct. Currently supported
100    /// ether type numbers are:
101    ///
102    /// * `ether_type::IPV4`
103    /// * `ether_type::IPV6`
104    /// * `ether_type::VLAN_TAGGED_FRAME`
105    /// * `ether_type::PROVIDER_BRIDGING`
106    /// * `ether_type::VLAN_DOUBLE_TAGGED_FRAME`
107    ///
108    /// If an unsupported ether type is given the given slice will be set as payload
109    /// and all other fields will be set to `None`.
110    ///
111    /// # Example
112    ///
113    /// Basic usage:
114    ///
115    ///```
116    /// # use etherparse::{Ethernet2Header, PacketBuilder};
117    /// # let builder = PacketBuilder::
118    /// #    ethernet2([1,2,3,4,5,6],     //source mac
119    /// #               [7,8,9,10,11,12]) //destination mac
120    /// #    .ipv4([192,168,1,1], //source ip
121    /// #          [192,168,1,2], //destination ip
122    /// #          20)            //time to life
123    /// #    .udp(21,    //source port
124    /// #         1234); //destination port
125    /// # // payload of the udp packet
126    /// # let payload = [1,2,3,4,5,6,7,8];
127    /// # // get some memory to store the serialized data
128    /// # let mut complete_packet = Vec::<u8>::with_capacity(
129    /// #     builder.size(payload.len())
130    /// # );
131    /// # builder.write(&mut complete_packet, &payload).unwrap();
132    /// #
133    /// # // skip ethernet 2 header so we can parse from there downwards
134    /// # let packet = &complete_packet[Ethernet2Header::LEN..];
135    /// #
136    /// use etherparse::{ether_type, LaxSlicedPacket};
137    ///
138    /// let packet = LaxSlicedPacket::from_ether_type(ether_type::IPV4, packet);
139    /// if let Some((stop_err, error_layer)) = packet.stop_err.as_ref() {
140    ///     // in case an error is encountered parsing is stopped
141    ///     println!("Error on layer {}: {:?}", error_layer, stop_err);
142    /// }
143    ///
144    /// // parts that could be parsed without error
145    /// println!("link: {:?}", packet.link);
146    /// println!("link_exts: {:?}", packet.link_exts); // vlan & macsec
147    /// println!("net: {:?}", packet.net); // ip & arp
148    /// println!("transport: {:?}", packet.transport);
149    ///
150    /// ```
151    pub fn from_ether_type(ether_type: EtherType, slice: &'a [u8]) -> LaxSlicedPacket<'a> {
152        LaxSlicedPacketCursor::parse_from_ether_type(ether_type, slice)
153    }
154
155    /// Separates a network packet slice into different slices containing
156    /// the headers from the ip header downwards with lax length checks
157    /// and will still return a result even if an error is encountered in
158    /// a layer (except IP).
159    ///
160    /// This function has two main differences to `SlicedPacket::from_ip`:
161    ///
162    /// * Errors encountered bellow the IpHeader will only stop the parsing and
163    ///   return an `Ok` with the successfully parsed parts and the error as optional.
164    ///   Only if an unrecoverable error is encountered in the IP header itself an
165    ///   `Err` is returned.
166    /// * Length in the IP header & UDP headers are allowed to be inconsistent with the
167    ///   given slice length (e.g. data is missing from the slice). In this case it falls
168    ///   back to the length of slice. See [`LaxIpSlice::from_slice`] for a detailed
169    ///   description of when the slice length is used as a fallback.
170    ///
171    /// The result is returned as a [`SlicedPacket`] struct. This function
172    /// assumes the given data starts with an IPv4 or IPv6 header.
173    ///
174    /// # Examples
175    ///
176    /// Basic usage:
177    ///
178    ///```
179    /// # use etherparse::{PacketBuilder, IpSlice, LenSource};
180    /// # let builder = PacketBuilder::
181    /// #    ipv4([192,168,1,1], //source ip
182    /// #         [192,168,1,2], //destination ip
183    /// #         20)            //time to life
184    /// #    .udp(21,    //source port
185    /// #         1234); //destination port
186    /// #    //payload of the udp packet
187    /// #    let payload = [1,2,3,4,5,6,7,8];
188    /// #    //get some memory to store the serialized data
189    /// #    let mut packet = Vec::<u8>::with_capacity(
190    /// #                            builder.size(payload.len()));
191    /// #    builder.write(&mut packet, &payload).unwrap();
192    /// use etherparse::LaxSlicedPacket;
193    ///
194    /// match LaxSlicedPacket::from_ip(&packet) {
195    ///     Err(value) => {
196    ///         // An error is returned in case the ip header could
197    ///         // not parsed (other errors are stored in the "stop_err" field)
198    ///         println!("Err {:?}", value)
199    ///     },
200    ///     Ok(value) => {
201    ///         if let Some((stop_err, error_layer)) = value.stop_err.as_ref() {
202    ///             // error is encountered after the ip header (stops parsing)
203    ///             println!("Error on layer {}: {:?}", error_layer, stop_err);
204    ///         }
205    ///
206    ///         // link & vlan fields are empty when parsing from ip downwards
207    ///         assert_eq!(None, value.link);
208    ///         assert!(value.link_exts.is_empty());
209    ///
210    ///         // net (ip) & transport (udp or tcp)
211    ///         println!("net: {:?}", value.net);
212    ///         if let Some(ip_payload) = value.net.as_ref().map(|net| net.ip_payload_ref()).flatten() {
213    ///             // the ip payload len_source field can be used to check
214    ///             // if the slice length was used as a fallback value
215    ///             if ip_payload.len_source == LenSource::Slice {
216    ///                 println!("  Used slice length as fallback to identify the IP payload");
217    ///             } else {
218    ///                 println!("  IP payload could correctly be identified via the length field in the header");
219    ///             }
220    ///         }
221    ///         println!("transport: {:?}", value.transport);
222    ///     }
223    /// };
224    /// ```
225    pub fn from_ip(slice: &'a [u8]) -> Result<LaxSlicedPacket<'a>, err::ip::LaxHeaderSliceError> {
226        LaxSlicedPacketCursor::parse_from_ip(slice)
227    }
228
229    /// Single or double vlan headers if present.
230    pub fn vlan(&self) -> Option<VlanSlice<'a>> {
231        let mut result = None;
232        for ext in &self.link_exts {
233            if let LaxLinkExtSlice::Vlan(s) = ext {
234                if let Some(outer) = result {
235                    return Some(VlanSlice::DoubleVlan(DoubleVlanSlice {
236                        outer,
237                        inner: s.clone(),
238                    }));
239                } else {
240                    result = Some(s.clone());
241                }
242            }
243        }
244        result.map(VlanSlice::SingleVlan)
245    }
246
247    /// Returns the VLAN ids present in this packet.
248    pub fn vlan_ids(&self) -> ArrayVec<VlanId, { SlicedPacket::LINK_EXTS_CAP }> {
249        let mut result = ArrayVec::<VlanId, { SlicedPacket::LINK_EXTS_CAP }>::new_const();
250        for e in &self.link_exts {
251            if let LaxLinkExtSlice::Vlan(s) = e {
252                // SAFETY: Safe as the vlan ids array has the same size as slice.link_exts.
253                unsafe {
254                    result.push_unchecked(s.vlan_identifier());
255                }
256            }
257        }
258        result
259    }
260
261    /// Returns the last ether payload of the packet (if one is present).
262    ///
263    /// If VLAN header is present the payload after the most inner VLAN
264    /// header is returned and if there is no VLAN header is present in the
265    /// link field is returned.
266    pub fn ether_payload(&self) -> Option<LaxEtherPayloadSlice<'a>> {
267        if let Some(link_ext) = self.link_exts.last() {
268            match link_ext {
269                LaxLinkExtSlice::Vlan(vlan_slice) => Some(LaxEtherPayloadSlice {
270                    incomplete: false,
271                    ether_type: vlan_slice.ether_type(),
272                    len_source: {
273                        let mut len_source = LenSource::Slice;
274                        for ext in &self.link_exts {
275                            if let Some(l) = ext.payload().as_ref() {
276                                if l.len_source != LenSource::Slice {
277                                    len_source = l.len_source;
278                                }
279                            }
280                        }
281                        len_source
282                    },
283                    payload: vlan_slice.payload_slice(),
284                }),
285                LaxLinkExtSlice::Macsec(macsec_slice) => macsec_slice.ether_payload(),
286            }
287        } else if let Some(link) = self.link.as_ref() {
288            match link {
289                LinkSlice::Ethernet2(e) => {
290                    let p = e.payload();
291                    Some(LaxEtherPayloadSlice {
292                        incomplete: false,
293                        ether_type: p.ether_type,
294                        len_source: LenSource::Slice,
295                        payload: p.payload,
296                    })
297                }
298                LinkSlice::LinuxSll(e) => match e.protocol_type() {
299                    LinuxSllProtocolType::EtherType(_)
300                    | LinuxSllProtocolType::LinuxNonstandardEtherType(_) => {
301                        let p = EtherPayloadSlice::try_from(e.payload()).ok()?;
302                        Some(LaxEtherPayloadSlice {
303                            incomplete: false,
304                            ether_type: p.ether_type,
305                            len_source: LenSource::Slice,
306                            payload: p.payload,
307                        })
308                    }
309                    _ => None,
310                },
311                LinkSlice::EtherPayload(p) => Some(LaxEtherPayloadSlice {
312                    incomplete: false,
313                    ether_type: p.ether_type,
314                    len_source: LenSource::Slice,
315                    payload: p.payload,
316                }),
317                LinkSlice::LinuxSllPayload(e) => match e.protocol_type {
318                    LinuxSllProtocolType::EtherType(_)
319                    | LinuxSllProtocolType::LinuxNonstandardEtherType(_) => {
320                        let p = EtherPayloadSlice::try_from(e.clone()).ok()?;
321                        Some(LaxEtherPayloadSlice {
322                            incomplete: false,
323                            ether_type: p.ether_type,
324                            len_source: LenSource::Slice,
325                            payload: p.payload,
326                        })
327                    }
328                    _ => None,
329                },
330            }
331        } else {
332            None
333        }
334    }
335
336    /// Return the IP payload after the the IP header and the IP extension
337    /// headers (if one is present).
338    pub fn ip_payload(&self) -> Option<&LaxIpPayloadSlice<'a>> {
339        if let Some(net) = self.net.as_ref() {
340            use LaxNetSlice::*;
341            match net {
342                Ipv4(v) => Some(v.payload()),
343                Ipv6(v) => Some(v.payload()),
344                Arp(_) => None,
345            }
346        } else {
347            None
348        }
349    }
350}
351
352#[cfg(test)]
353mod test {
354    use std::vec::Vec;
355
356    use super::*;
357    use crate::err::{packet::SliceError, LenError};
358    use crate::test_packet::TestPacket;
359
360    const VLAN_ETHER_TYPES: [EtherType; 3] = [
361        ether_type::VLAN_TAGGED_FRAME,
362        ether_type::PROVIDER_BRIDGING,
363        ether_type::VLAN_DOUBLE_TAGGED_FRAME,
364    ];
365    const MACSEC_ETHER_TYPES: [EtherType; 1] = [ether_type::MACSEC];
366
367    #[test]
368    fn clone_eq() {
369        let header = LaxSlicedPacket {
370            link: None,
371            link_exts: ArrayVec::new_const(),
372            net: None,
373            transport: None,
374            stop_err: None,
375        };
376        assert_eq!(header.clone(), header);
377    }
378
379    #[test]
380    fn debug() {
381        use alloc::format;
382        let header = LaxSlicedPacket {
383            link: None,
384            link_exts: ArrayVec::new_const(),
385            net: None,
386            transport: None,
387            stop_err: None,
388        };
389        assert_eq!(
390            format!("{:?}", header),
391            format!(
392                "LaxSlicedPacket {{ link: {:?}, link_exts: {:?}, net: {:?}, transport: {:?}, stop_err: {:?} }}",
393                header.link, header.link_exts, header.net, header.transport, header.stop_err
394            )
395        );
396    }
397
398    #[test]
399    fn vlan_vlan_ids() {
400        // no content
401        assert_eq!(
402            LaxSlicedPacket {
403                link: None,
404                link_exts: ArrayVec::new_const(),
405                net: None,
406                transport: None,
407                stop_err: None
408            }
409            .vlan(),
410            None
411        );
412        assert_eq!(
413            LaxSlicedPacket {
414                link: None,
415                link_exts: ArrayVec::new_const(),
416                net: None,
417                transport: None,
418                stop_err: None
419            }
420            .vlan_ids(),
421            ArrayVec::<VlanId, 3>::new_const()
422        );
423
424        // single vlan header
425        {
426            let payload = [1, 2, 3, 4];
427            let mut buf = Vec::with_capacity(SingleVlanHeader::LEN + 4);
428            buf.extend_from_slice(
429                &SingleVlanHeader {
430                    pcp: VlanPcp::ZERO,
431                    drop_eligible_indicator: false,
432                    vlan_id: VlanId::try_new(1).unwrap(),
433                    ether_type: EtherType::WAKE_ON_LAN,
434                }
435                .to_bytes(),
436            );
437            buf.extend_from_slice(&payload);
438
439            let slice = LaxSlicedPacket::from_ether_type(ether_type::VLAN_TAGGED_FRAME, &buf);
440
441            assert_eq!(
442                slice.vlan(),
443                Some(VlanSlice::SingleVlan(SingleVlanSlice { slice: &buf[..] }))
444            );
445            assert_eq!(slice.vlan_ids(), {
446                let mut ids = ArrayVec::<VlanId, 3>::new_const();
447                ids.push(VlanId::try_new(1).unwrap());
448                ids
449            });
450        }
451
452        // two vlan header
453        {
454            let payload = [1, 2, 3, 4];
455            let mut buf = Vec::with_capacity(SingleVlanHeader::LEN * 2 + 4);
456            buf.extend_from_slice(
457                &SingleVlanHeader {
458                    pcp: VlanPcp::ZERO,
459                    drop_eligible_indicator: false,
460                    vlan_id: VlanId::try_new(1).unwrap(),
461                    ether_type: EtherType::VLAN_TAGGED_FRAME,
462                }
463                .to_bytes(),
464            );
465            buf.extend_from_slice(
466                &SingleVlanHeader {
467                    pcp: VlanPcp::ZERO,
468                    drop_eligible_indicator: false,
469                    vlan_id: VlanId::try_new(2).unwrap(),
470                    ether_type: EtherType::WAKE_ON_LAN,
471                }
472                .to_bytes(),
473            );
474            buf.extend_from_slice(&payload);
475
476            let slice =
477                LaxSlicedPacket::from_ether_type(ether_type::VLAN_DOUBLE_TAGGED_FRAME, &buf);
478
479            assert_eq!(
480                slice.vlan(),
481                Some(VlanSlice::DoubleVlan(DoubleVlanSlice {
482                    outer: SingleVlanSlice { slice: &buf },
483                    inner: SingleVlanSlice {
484                        slice: &buf[SingleVlanHeader::LEN..]
485                    },
486                }))
487            );
488            assert_eq!(slice.vlan_ids(), {
489                let mut ids = ArrayVec::<VlanId, 3>::new_const();
490                ids.push(VlanId::try_new(1).unwrap());
491                ids.push(VlanId::try_new(2).unwrap());
492                ids
493            });
494        }
495
496        // two vlan header with macsec
497        {
498            let payload = [1, 2, 3, 4];
499            let macsec = MacsecHeader {
500                ptype: MacsecPType::Unmodified(EtherType::VLAN_DOUBLE_TAGGED_FRAME),
501                endstation_id: false,
502                scb: false,
503                an: MacsecAn::ZERO,
504                short_len: MacsecShortLen::ZERO,
505                packet_nr: 0,
506                sci: None,
507            };
508            let mut buf = Vec::with_capacity(macsec.header_len() + SingleVlanHeader::LEN * 2 + 4);
509            buf.extend_from_slice(&macsec.to_bytes());
510            buf.extend_from_slice(
511                &SingleVlanHeader {
512                    pcp: VlanPcp::ZERO,
513                    drop_eligible_indicator: false,
514                    vlan_id: VlanId::try_new(1).unwrap(),
515                    ether_type: EtherType::VLAN_TAGGED_FRAME,
516                }
517                .to_bytes(),
518            );
519            buf.extend_from_slice(
520                &SingleVlanHeader {
521                    pcp: VlanPcp::ZERO,
522                    drop_eligible_indicator: false,
523                    vlan_id: VlanId::try_new(2).unwrap(),
524                    ether_type: EtherType::WAKE_ON_LAN,
525                }
526                .to_bytes(),
527            );
528            buf.extend_from_slice(&payload);
529
530            let slice = LaxSlicedPacket::from_ether_type(ether_type::MACSEC, &buf);
531
532            let vlan_start = macsec.header_len();
533            assert_eq!(
534                slice.vlan(),
535                Some(VlanSlice::DoubleVlan(DoubleVlanSlice {
536                    outer: SingleVlanSlice {
537                        slice: &buf[vlan_start..]
538                    },
539                    inner: SingleVlanSlice {
540                        slice: &buf[vlan_start + SingleVlanHeader::LEN..]
541                    },
542                }))
543            );
544            assert_eq!(slice.vlan_ids(), {
545                let mut ids = ArrayVec::<VlanId, 3>::new_const();
546                ids.push(VlanId::try_new(1).unwrap());
547                ids.push(VlanId::try_new(2).unwrap());
548                ids
549            });
550        }
551
552        // three vlan header
553        {
554            let payload = [1, 2, 3, 4];
555            let mut buf = Vec::with_capacity(SingleVlanHeader::LEN * 3 + 4);
556            buf.extend_from_slice(
557                &SingleVlanHeader {
558                    pcp: VlanPcp::ZERO,
559                    drop_eligible_indicator: false,
560                    vlan_id: VlanId::try_new(1).unwrap(),
561                    ether_type: EtherType::VLAN_TAGGED_FRAME,
562                }
563                .to_bytes(),
564            );
565            buf.extend_from_slice(
566                &SingleVlanHeader {
567                    pcp: VlanPcp::ZERO,
568                    drop_eligible_indicator: false,
569                    vlan_id: VlanId::try_new(2).unwrap(),
570                    ether_type: EtherType::VLAN_TAGGED_FRAME,
571                }
572                .to_bytes(),
573            );
574            buf.extend_from_slice(
575                &SingleVlanHeader {
576                    pcp: VlanPcp::ZERO,
577                    drop_eligible_indicator: false,
578                    vlan_id: VlanId::try_new(3).unwrap(),
579                    ether_type: EtherType::WAKE_ON_LAN,
580                }
581                .to_bytes(),
582            );
583            buf.extend_from_slice(&payload);
584
585            let slice =
586                LaxSlicedPacket::from_ether_type(ether_type::VLAN_DOUBLE_TAGGED_FRAME, &buf);
587
588            assert_eq!(
589                slice.vlan(),
590                Some(VlanSlice::DoubleVlan(DoubleVlanSlice {
591                    outer: SingleVlanSlice { slice: &buf },
592                    inner: SingleVlanSlice {
593                        slice: &buf[SingleVlanHeader::LEN..]
594                    },
595                }))
596            );
597            assert_eq!(slice.vlan_ids(), {
598                let mut ids = ArrayVec::<VlanId, 3>::new_const();
599                ids.push(VlanId::try_new(1).unwrap());
600                ids.push(VlanId::try_new(2).unwrap());
601                ids.push(VlanId::try_new(3).unwrap());
602                ids
603            });
604        }
605    }
606
607    #[test]
608    fn ether_payload() {
609        use alloc::vec::*;
610
611        // no content
612        assert_eq!(
613            LaxSlicedPacket {
614                link: None,
615                link_exts: ArrayVec::new_const(),
616                net: None,
617                transport: None,
618                stop_err: None
619            }
620            .ether_payload(),
621            None
622        );
623
624        // only ethernet header II
625        {
626            let payload = [1, 2, 3, 4];
627            let mut buf = Vec::with_capacity(Ethernet2Header::LEN + 4);
628            buf.extend_from_slice(
629                &Ethernet2Header {
630                    ether_type: EtherType::WAKE_ON_LAN,
631                    ..Default::default()
632                }
633                .to_bytes(),
634            );
635            buf.extend_from_slice(&payload);
636            assert_eq!(
637                LaxSlicedPacket::from_ethernet(&buf)
638                    .unwrap()
639                    .ether_payload(),
640                Some(LaxEtherPayloadSlice {
641                    incomplete: false,
642                    ether_type: EtherType::WAKE_ON_LAN,
643                    len_source: LenSource::Slice,
644                    payload: &payload
645                })
646            );
647        }
648
649        // ether type payload
650        {
651            let payload = [1, 2, 3, 4];
652            assert_eq!(
653                LaxSlicedPacket {
654                    link: Some(LinkSlice::EtherPayload(EtherPayloadSlice {
655                        ether_type: EtherType::WAKE_ON_LAN,
656                        len_source: LenSource::Slice,
657                        payload: &payload
658                    })),
659                    link_exts: ArrayVec::new_const(),
660                    net: None,
661                    transport: None,
662                    stop_err: None,
663                }
664                .ether_payload(),
665                Some(LaxEtherPayloadSlice {
666                    incomplete: false,
667                    ether_type: EtherType::WAKE_ON_LAN,
668                    len_source: LenSource::Slice,
669                    payload: &payload
670                })
671            );
672        }
673
674        // single vlan header
675        {
676            let payload = [1, 2, 3, 4];
677            let mut buf = Vec::with_capacity(Ethernet2Header::LEN + SingleVlanHeader::LEN + 4);
678            buf.extend_from_slice(
679                &Ethernet2Header {
680                    ether_type: EtherType::VLAN_TAGGED_FRAME,
681                    ..Default::default()
682                }
683                .to_bytes(),
684            );
685            buf.extend_from_slice(
686                &SingleVlanHeader {
687                    ether_type: EtherType::WAKE_ON_LAN,
688                    ..Default::default()
689                }
690                .to_bytes(),
691            );
692            buf.extend_from_slice(&payload);
693            assert_eq!(
694                LaxSlicedPacket::from_ethernet(&buf)
695                    .unwrap()
696                    .ether_payload(),
697                Some(LaxEtherPayloadSlice {
698                    incomplete: false,
699                    ether_type: EtherType::WAKE_ON_LAN,
700                    len_source: LenSource::Slice,
701                    payload: &payload
702                })
703            );
704        }
705
706        // double vlan header
707        {
708            let payload = [1, 2, 3, 4];
709            let mut buf = Vec::with_capacity(Ethernet2Header::LEN + SingleVlanHeader::LEN * 2 + 4);
710            buf.extend_from_slice(
711                &Ethernet2Header {
712                    ether_type: EtherType::VLAN_DOUBLE_TAGGED_FRAME,
713                    ..Default::default()
714                }
715                .to_bytes(),
716            );
717            buf.extend_from_slice(
718                &SingleVlanHeader {
719                    ether_type: EtherType::VLAN_TAGGED_FRAME,
720                    ..Default::default()
721                }
722                .to_bytes(),
723            );
724            buf.extend_from_slice(
725                &SingleVlanHeader {
726                    ether_type: EtherType::WAKE_ON_LAN,
727                    ..Default::default()
728                }
729                .to_bytes(),
730            );
731            buf.extend_from_slice(&payload);
732            assert_eq!(
733                LaxSlicedPacket::from_ethernet(&buf)
734                    .unwrap()
735                    .ether_payload(),
736                Some(LaxEtherPayloadSlice {
737                    incomplete: false,
738                    ether_type: EtherType::WAKE_ON_LAN,
739                    len_source: LenSource::Slice,
740                    payload: &payload
741                })
742            );
743        }
744    }
745
746    #[test]
747    fn ip_payload() {
748        use alloc::vec::*;
749
750        // no content
751        assert_eq!(
752            LaxSlicedPacket {
753                link: None,
754                link_exts: ArrayVec::new_const(),
755                net: None,
756                transport: None,
757                stop_err: None,
758            }
759            .ip_payload(),
760            None
761        );
762
763        // ipv4
764        {
765            let payload = [1, 2, 3, 4];
766            let mut buf = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
767            buf.extend_from_slice(
768                &Ipv4Header {
769                    protocol: IpNumber::ARIS,
770                    total_len: Ipv4Header::MIN_LEN_U16 + 4,
771                    ..Default::default()
772                }
773                .to_bytes(),
774            );
775            buf.extend_from_slice(&payload);
776            assert_eq!(
777                LaxSlicedPacket::from_ip(&buf).unwrap().ip_payload(),
778                Some(&LaxIpPayloadSlice {
779                    payload: &payload,
780                    ip_number: IpNumber::ARIS,
781                    fragmented: false,
782                    len_source: LenSource::Ipv4HeaderTotalLen,
783                    incomplete: false,
784                })
785            );
786        }
787
788        // ipv6
789        {
790            let payload = [1, 2, 3, 4];
791            let mut buf = Vec::with_capacity(Ipv6Header::LEN + 4);
792            buf.extend_from_slice(
793                &Ipv6Header {
794                    payload_length: 4,
795                    next_header: IpNumber::ARGUS,
796                    ..Default::default()
797                }
798                .to_bytes(),
799            );
800            buf.extend_from_slice(&payload);
801            assert_eq!(
802                LaxSlicedPacket::from_ip(&buf).unwrap().ip_payload(),
803                Some(&LaxIpPayloadSlice {
804                    payload: &payload,
805                    ip_number: IpNumber::ARGUS,
806                    fragmented: false,
807                    len_source: LenSource::Ipv6HeaderPayloadLen,
808                    incomplete: false,
809                })
810            );
811        }
812    }
813
814    #[test]
815    fn from_x_slice() {
816        // no eth
817        from_x_slice_link_exts_variants(&TestPacket {
818            link: None,
819            link_exts: ArrayVec::new_const(),
820            net: None,
821            transport: None,
822        });
823
824        // eth
825        {
826            let eth = Ethernet2Header {
827                source: [1, 2, 3, 4, 5, 6],
828                destination: [1, 2, 3, 4, 5, 6],
829                ether_type: 0.into(),
830            };
831            let test = TestPacket {
832                link: Some(LinkHeader::Ethernet2(eth.clone())),
833                link_exts: ArrayVec::new_const(),
834                net: None,
835                transport: None,
836            };
837
838            // ok ethernet header (with unknown next)
839            from_x_slice_link_exts_variants(&test);
840
841            // eth len error
842            {
843                let data = test.to_vec(&[]);
844                for len in 0..data.len() {
845                    assert_test_result(&test, &[], &data[..len], None, None);
846                }
847            }
848        }
849
850        // unknown ether_type
851        {
852            let payload = [1, 2, 3, 4];
853            let actual = LaxSlicedPacket::from_ether_type(0.into(), &payload);
854            assert_eq!(
855                actual.link,
856                Some(LinkSlice::EtherPayload(EtherPayloadSlice {
857                    ether_type: 0.into(),
858                    len_source: LenSource::Slice,
859                    payload: &payload
860                }))
861            );
862            assert!(actual.link_exts.is_empty());
863            assert_eq!(None, actual.net);
864            assert_eq!(None, actual.transport);
865            assert_eq!(None, actual.stop_err);
866        }
867    }
868
869    fn from_x_slice_link_exts_variants(base: &TestPacket) {
870        #[derive(Copy, Clone, Eq, PartialEq)]
871        enum Ext {
872            Macsec,
873            VlanTaggedFrame,
874            VlanDoubleTaggedFrame,
875            ProviderBridging,
876        }
877
878        impl Ext {
879            pub fn ether_type(&self) -> EtherType {
880                match self {
881                    Ext::Macsec => EtherType::MACSEC,
882                    Ext::VlanTaggedFrame => EtherType::VLAN_TAGGED_FRAME,
883                    Ext::VlanDoubleTaggedFrame => EtherType::VLAN_DOUBLE_TAGGED_FRAME,
884                    Ext::ProviderBridging => EtherType::PROVIDER_BRIDGING,
885                }
886            }
887
888            pub fn add(&self, base: &TestPacket) -> TestPacket {
889                let mut test = base.clone();
890                test.set_ether_type(self.ether_type());
891                test.link_exts
892                    .try_push(match self {
893                        Ext::Macsec => LinkExtHeader::Macsec(MacsecHeader {
894                            ptype: MacsecPType::Unmodified(EtherType(3)),
895                            endstation_id: false,
896                            scb: false,
897                            an: MacsecAn::ZERO,
898                            short_len: MacsecShortLen::ZERO,
899                            packet_nr: 0,
900                            sci: None,
901                        }),
902                        Ext::VlanTaggedFrame
903                        | Ext::VlanDoubleTaggedFrame
904                        | Ext::ProviderBridging => LinkExtHeader::Vlan(SingleVlanHeader {
905                            pcp: VlanPcp::ZERO,
906                            drop_eligible_indicator: false,
907                            vlan_id: VlanId::try_new(1).unwrap(),
908                            ether_type: 3.into(),
909                        }),
910                    })
911                    .unwrap();
912                test
913            }
914        }
915
916        let len_errors = |test: &TestPacket| {
917            let data = test.to_vec(&[]);
918            let req_len = test.link_exts.last().unwrap().header_len();
919            for len in 0..req_len {
920                let base_len = test.len(&[]) - req_len;
921
922                let (err_req_len, err_layer) = match test.link_exts.last().unwrap() {
923                    LinkExtHeader::Vlan(h) => (h.header_len(), Layer::VlanHeader),
924                    LinkExtHeader::Macsec(_) => {
925                        if len < 6 {
926                            (6, Layer::MacsecHeader)
927                        } else {
928                            (req_len, Layer::MacsecHeader)
929                        }
930                    }
931                };
932
933                let mut len_source = LenSource::Slice;
934                for prev_exts in test.link_exts.iter().rev().skip(1) {
935                    if let LinkExtHeader::Macsec(m) = prev_exts {
936                        if m.short_len != MacsecShortLen::ZERO {
937                            len_source = LenSource::MacsecShortLength;
938                        }
939                    }
940                }
941
942                let err = LenError {
943                    required_len: err_req_len,
944                    len,
945                    len_source,
946                    layer: err_layer,
947                    layer_start_offset: base_len,
948                };
949                assert_test_result(
950                    &test,
951                    &[],
952                    &data[..base_len + len],
953                    None,
954                    Some((SliceError::Len(err.clone()), err_layer)),
955                );
956            }
957        };
958
959        let content_errors = |test: &TestPacket| {
960            if let Some(LinkExtHeader::Macsec(last)) = test.link_exts.last() {
961                let mut data = test.to_vec(&[]);
962
963                // inject bad version id
964                let macsec_offset = data.len() - last.header_len();
965                data[macsec_offset] = data[macsec_offset] | 0b1000_0000;
966
967                assert_test_result(
968                    &{
969                        let mut expected = test.clone();
970                        expected.link_exts.pop();
971                        expected
972                    },
973                    &[],
974                    &data,
975                    None,
976                    Some((
977                        SliceError::Macsec(err::macsec::HeaderError::UnexpectedVersion),
978                        Layer::MacsecHeader,
979                    )),
980                );
981            }
982        };
983
984        // extensions
985        let extensions = [
986            Ext::Macsec,
987            Ext::VlanTaggedFrame,
988            Ext::VlanDoubleTaggedFrame,
989            Ext::ProviderBridging,
990        ];
991
992        // none
993        from_x_slice_net_variants(base);
994
995        // add up to three layers of extensions
996        for ext0 in extensions {
997            let test0 = ext0.add(base);
998            from_x_slice_net_variants(&test0);
999            len_errors(&test0);
1000            content_errors(&test0);
1001
1002            for ext1 in extensions {
1003                let test1 = ext1.add(&test0);
1004                from_x_slice_net_variants(&test1);
1005                len_errors(&test1);
1006                content_errors(&test1);
1007
1008                for ext2 in extensions {
1009                    let test2 = ext2.add(&test1);
1010                    from_x_slice_net_variants(&test2);
1011                    len_errors(&test2);
1012                    content_errors(&test2);
1013
1014                    // above max supported link ext
1015                    for ext3 in extensions {
1016                        let mut test3 = test2.clone();
1017                        let l = test3.link_exts.last_mut().unwrap();
1018                        match l {
1019                            LinkExtHeader::Vlan(s) => {
1020                                s.ether_type = ext3.ether_type();
1021                            }
1022                            LinkExtHeader::Macsec(m) => {
1023                                m.ptype = MacsecPType::Unmodified(ext3.ether_type());
1024                            }
1025                        }
1026                        from_x_slice_assert_ok(&test3);
1027                    }
1028                }
1029            }
1030        }
1031    }
1032
1033    fn from_x_slice_net_variants(base: &TestPacket) {
1034        // none
1035        from_x_slice_transport_variants(base);
1036
1037        // ipv4
1038        for fragmented in [false, true] {
1039            let ipv4 = {
1040                let mut ipv4 =
1041                    Ipv4Header::new(0, 1, 2.into(), [3, 4, 5, 6], [7, 8, 9, 10]).unwrap();
1042                ipv4.more_fragments = fragmented;
1043                ipv4
1044            };
1045
1046            {
1047                let mut test = base.clone();
1048                test.set_ether_type(ether_type::IPV4);
1049                test.net = Some(NetHeaders::Ipv4(ipv4.clone(), Default::default()));
1050                test.set_payload_len(0);
1051
1052                // ok ipv4
1053                from_x_slice_transport_variants(&test);
1054
1055                // ipv4 len error
1056                {
1057                    let data = test.to_vec(&[]);
1058                    for len in 0..ipv4.header_len() {
1059                        let base_len = test.len(&[]) - ipv4.header_len();
1060
1061                        let err = LenError {
1062                            required_len: if len < 1 { 1 } else { ipv4.header_len() },
1063                            len,
1064                            len_source: LenSource::Slice,
1065                            layer: if len < 1 {
1066                                Layer::IpHeader
1067                            } else {
1068                                Layer::Ipv4Header
1069                            },
1070                            layer_start_offset: base_len,
1071                        };
1072
1073                        assert_test_result(
1074                            &test,
1075                            &[],
1076                            &data[..base_len + len],
1077                            Some(err::ip::LaxHeaderSliceError::Len(err.clone())),
1078                            Some((SliceError::Len(err.clone()), Layer::IpHeader)),
1079                        );
1080                    }
1081                }
1082
1083                // ipv4 content error (ihl length too small)
1084                {
1085                    use err::ip::HeaderError::*;
1086
1087                    let mut data = test.to_vec(&[]);
1088                    let ipv4_offset = data.len() - ipv4.header_len();
1089
1090                    // set the ihl to 0 to trigger a content error
1091                    data[ipv4_offset] = 0b1111_0000 & data[ipv4_offset];
1092
1093                    assert_test_result(
1094                        &test,
1095                        &[],
1096                        &data,
1097                        Some(err::ip::LaxHeaderSliceError::Content(
1098                            Ipv4HeaderLengthSmallerThanHeader { ihl: 0 },
1099                        )),
1100                        Some((
1101                            SliceError::Ip(Ipv4HeaderLengthSmallerThanHeader { ihl: 0 }),
1102                            Layer::IpHeader,
1103                        )),
1104                    );
1105                }
1106
1107                // ipv 4total length too small (does not change the output)
1108                {
1109                    let mut data = test.to_vec(&[]);
1110                    let ipv4_offset = data.len() - ipv4.header_len();
1111
1112                    // set the total length to 0 to trigger a content error
1113                    data[ipv4_offset + 2] = 0;
1114                    data[ipv4_offset + 3] = 0;
1115
1116                    let mut mod_test = test.clone();
1117                    mod_test.net = Some({
1118                        let (h, e) = test.net.as_ref().map(|v| v.ipv4_ref()).flatten().unwrap();
1119                        let mut ipv4 = h.clone();
1120                        ipv4.total_len = 0;
1121                        NetHeaders::Ipv4(ipv4, e.clone())
1122                    });
1123
1124                    assert_test_result(&mod_test, &[], &data, None, None);
1125                }
1126            }
1127
1128            // ipv4 extension content error
1129            {
1130                let auth = IpAuthHeader::new(0.into(), 1, 2, &[]).unwrap();
1131
1132                let mut test = base.clone();
1133                test.set_ether_type(ether_type::IPV4);
1134                test.net = Some(NetHeaders::Ipv4(
1135                    {
1136                        let mut ipv4 = ipv4.clone();
1137                        ipv4.protocol = ip_number::AUTH;
1138                        ipv4
1139                    },
1140                    Ipv4Extensions {
1141                        auth: Some(auth.clone()),
1142                    },
1143                ));
1144                test.set_payload_len(0);
1145
1146                // ok ipv4 & extension
1147                from_x_slice_transport_variants(&test);
1148
1149                // ipv4 extension len error
1150                for len in 0..auth.header_len() {
1151                    // set payload length
1152                    let mut test = test.clone();
1153                    test.set_payload_len_ip(-1 * (auth.header_len() as isize) + (len as isize));
1154
1155                    let data = test.to_vec(&[]);
1156                    let base_len = test.len(&[]) - auth.header_len();
1157
1158                    let err = LenError {
1159                        required_len: auth.header_len(),
1160                        len,
1161                        len_source: LenSource::Ipv4HeaderTotalLen,
1162                        layer: Layer::IpAuthHeader,
1163                        layer_start_offset: base_len,
1164                    };
1165
1166                    assert_test_result(
1167                        &test,
1168                        &[],
1169                        &data,
1170                        None,
1171                        Some((SliceError::Len(err.clone()), Layer::IpAuthHeader)),
1172                    );
1173                }
1174
1175                // ipv4 extension content error
1176                {
1177                    let mut data = test.to_vec(&[]);
1178                    let auth_offset = data.len() - auth.header_len();
1179
1180                    // set the icv len too smaller then allowed
1181                    data[auth_offset + 1] = 0;
1182
1183                    // expect an error
1184                    assert_test_result(
1185                        &test,
1186                        &[],
1187                        &data,
1188                        None,
1189                        Some((
1190                            SliceError::Ipv4Exts(err::ip_auth::HeaderError::ZeroPayloadLen),
1191                            Layer::IpAuthHeader,
1192                        )),
1193                    );
1194                }
1195            }
1196        }
1197
1198        // ipv6
1199        {
1200            let ipv6 = Ipv6Header {
1201                traffic_class: 0,
1202                flow_label: 1.try_into().unwrap(),
1203                payload_length: 2,
1204                next_header: 3.into(),
1205                hop_limit: 4,
1206                source: [0; 16],
1207                destination: [0; 16],
1208            };
1209
1210            // ipv6 header only
1211            {
1212                let mut test = base.clone();
1213                test.set_ether_type(ether_type::IPV6);
1214                test.net = Some(NetHeaders::Ipv6(ipv6.clone(), Default::default()));
1215                test.set_payload_len(0);
1216
1217                // ok ipv6
1218                from_x_slice_transport_variants(&test);
1219
1220                // header len ipv6
1221                {
1222                    let data = test.to_vec(&[]);
1223                    for len in 0..ipv6.header_len() {
1224                        let base_len = test.len(&[]) - ipv6.header_len();
1225
1226                        let err = err::LenError {
1227                            required_len: if len < 1 { 1 } else { ipv6.header_len() },
1228                            len,
1229                            len_source: LenSource::Slice,
1230                            layer: if len < 1 {
1231                                Layer::IpHeader
1232                            } else {
1233                                Layer::Ipv6Header
1234                            },
1235                            layer_start_offset: base_len,
1236                        };
1237
1238                        assert_test_result(
1239                            &test,
1240                            &[],
1241                            &data[..base_len + len],
1242                            Some(err::ip::LaxHeaderSliceError::Len(err.clone())),
1243                            Some((
1244                                SliceError::Len({
1245                                    if len < 1 {
1246                                        let mut err = err.clone();
1247                                        err.required_len = 1;
1248                                        err.layer = Layer::IpHeader;
1249                                        err
1250                                    } else {
1251                                        err.clone()
1252                                    }
1253                                }),
1254                                Layer::IpHeader,
1255                            )),
1256                        );
1257                    }
1258                }
1259
1260                // content error ipv6
1261                {
1262                    use err::ip::{HeaderError::*, LaxHeaderSliceError::Content};
1263
1264                    let mut data = test.to_vec(&[]);
1265
1266                    // inject an invalid ip version
1267                    let base_len = data.len() - ipv6.header_len();
1268                    data[base_len] = data[base_len] & 0b0000_1111;
1269
1270                    assert_test_result(
1271                        &test,
1272                        &[],
1273                        &data,
1274                        Some(Content(UnsupportedIpVersion { version_number: 0 })),
1275                        Some((
1276                            SliceError::Ip(UnsupportedIpVersion { version_number: 0 }),
1277                            Layer::IpHeader,
1278                        )),
1279                    );
1280                }
1281            }
1282
1283            // ipv6 + extension
1284            for fragment in [false, true] {
1285                let auth = IpAuthHeader::new(ip_number::GGP, 1, 2, &[]).unwrap();
1286                let frag = Ipv6FragmentHeader {
1287                    next_header: ip_number::AUTH,
1288                    fragment_offset: 0.try_into().unwrap(),
1289                    more_fragments: fragment,
1290                    identification: 3,
1291                };
1292
1293                let mut test = base.clone();
1294                test.set_ether_type(ether_type::IPV6);
1295                test.net = Some(NetHeaders::Ipv6(
1296                    {
1297                        let mut ipv6 = ipv6.clone();
1298                        ipv6.next_header = ip_number::IPV6_FRAG;
1299                        ipv6
1300                    },
1301                    {
1302                        let mut exts: Ipv6Extensions = Default::default();
1303                        exts.fragment = Some(frag.clone());
1304                        exts.auth = Some(auth.clone());
1305                        exts
1306                    },
1307                ));
1308                test.set_payload_len(0);
1309
1310                // ok ipv6 & extensions
1311                from_x_slice_transport_variants(&test);
1312
1313                // ipv6 extension len error
1314                for len in 0..auth.header_len() {
1315                    // set payload length
1316                    let mut test = test.clone();
1317                    test.set_payload_len_ip(-1 * (auth.header_len() as isize) + (len as isize));
1318
1319                    let data = test.to_vec(&[]);
1320                    let base_len = test.len(&[]) - auth.header_len();
1321
1322                    let err = LenError {
1323                        required_len: auth.header_len(),
1324                        len,
1325                        len_source: LenSource::Ipv6HeaderPayloadLen,
1326                        layer: Layer::IpAuthHeader,
1327                        layer_start_offset: base_len,
1328                    };
1329                    assert_test_result(
1330                        &test,
1331                        &[],
1332                        &data[..base_len + len],
1333                        None,
1334                        Some((SliceError::Len(err.clone()), Layer::IpAuthHeader)),
1335                    );
1336                }
1337
1338                // ipv6 extension content error (auth)
1339                {
1340                    let mut data = test.to_vec(&[]);
1341                    let auth_offset = data.len() - auth.header_len();
1342                    // set the icv len too smaller then allowed
1343                    data[auth_offset + 1] = 0;
1344
1345                    assert_test_result(
1346                        &test,
1347                        &[],
1348                        &data,
1349                        None,
1350                        Some((
1351                            SliceError::Ipv6Exts(err::ipv6_exts::HeaderError::IpAuth(
1352                                err::ip_auth::HeaderError::ZeroPayloadLen,
1353                            )),
1354                            Layer::IpAuthHeader,
1355                        )),
1356                    );
1357                }
1358
1359                // ipv6 extension content error (hop by hop not at start)
1360                {
1361                    let mut data = test.to_vec(&[]);
1362                    let auth_offset = data.len() - auth.header_len();
1363
1364                    // set the next header to be a hop-by-hop header to trigger a "not at start error"
1365                    data[auth_offset] = 0;
1366
1367                    assert_test_result(
1368                        &test,
1369                        &[],
1370                        &data,
1371                        None,
1372                        Some((
1373                            SliceError::Ipv6Exts(err::ipv6_exts::HeaderError::HopByHopNotAtStart),
1374                            Layer::Ipv6HopByHopHeader,
1375                        )),
1376                    );
1377                }
1378            }
1379        }
1380
1381        // arp
1382        {
1383            let arp = ArpPacket::new(
1384                ArpHardwareId::ETHERNET,
1385                EtherType::IPV4,
1386                ArpOperation::REPLY,
1387                &[0u8; 6],
1388                &[0u8; 4],
1389                &[0u8; 6],
1390                &[0u8; 4],
1391            )
1392            .unwrap();
1393
1394            let mut test = base.clone();
1395            test.set_ether_type(ether_type::ARP);
1396            test.net = Some(NetHeaders::Arp(arp.clone()));
1397            test.set_payload_len(0);
1398
1399            // ok arp
1400            from_x_slice_assert_ok(&test);
1401
1402            // len error
1403            {
1404                let data = test.to_vec(&[]);
1405                for len in 0..arp.packet_len() {
1406                    let base_len = test.len(&[]) - arp.packet_len();
1407
1408                    let err = err::LenError {
1409                        required_len: if len < 8 { 8 } else { arp.packet_len() },
1410                        len,
1411                        len_source: if len < 8 {
1412                            LenSource::Slice
1413                        } else {
1414                            LenSource::ArpAddrLengths
1415                        },
1416                        layer: Layer::Arp,
1417                        layer_start_offset: base_len,
1418                    };
1419
1420                    assert_test_result(
1421                        &test,
1422                        &[],
1423                        &data[..base_len + len],
1424                        Some(err::ip::LaxHeaderSliceError::Len(err.clone())),
1425                        Some((
1426                            SliceError::Len({
1427                                if len < 8 {
1428                                    let mut err = err.clone();
1429                                    err.required_len = 8;
1430                                    err.layer = Layer::Arp;
1431                                    err
1432                                } else {
1433                                    err.clone()
1434                                }
1435                            }),
1436                            Layer::Arp,
1437                        )),
1438                    );
1439                }
1440            }
1441        }
1442    }
1443
1444    fn from_x_slice_transport_variants(base: &TestPacket) {
1445        // none
1446        from_x_slice_assert_ok(base);
1447
1448        // transport can only be set if ip is present
1449        if let Some(ip) = &base.net {
1450            // udp
1451            {
1452                let udp = UdpHeader {
1453                    source_port: 1,
1454                    destination_port: 2,
1455                    length: 3,
1456                    checksum: 4,
1457                };
1458                let mut test = base.clone();
1459                test.net = Some({
1460                    let mut ip = match ip {
1461                        NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1462                        NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1463                        NetHeaders::Arp(_) => unreachable!(),
1464                    };
1465                    ip.set_next_headers(ip_number::UDP);
1466                    ip.into()
1467                });
1468                test.transport = Some(TransportHeader::Udp(udp.clone()));
1469                test.set_payload_len(0);
1470
1471                // ok decode
1472                from_x_slice_assert_ok(&test);
1473
1474                // length error
1475                if false == test.is_ip_payload_fragmented() {
1476                    for len in 0..udp.header_len() {
1477                        // build new test packet
1478                        let mut test = test.clone();
1479
1480                        // set payload length
1481                        test.set_payload_len_ip(len as isize);
1482
1483                        // generate data
1484                        let data = test.to_vec(&[]);
1485
1486                        let base_len = test.len(&[]) - udp.header_len();
1487                        let err = LenError {
1488                            required_len: udp.header_len(),
1489                            len,
1490                            len_source: match test.net.as_ref().unwrap() {
1491                                NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1492                                NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1493                                NetHeaders::Arp(_) => unreachable!(),
1494                            },
1495                            layer: Layer::UdpHeader,
1496                            layer_start_offset: base_len,
1497                        };
1498                        assert_test_result(
1499                            &test,
1500                            &[],
1501                            &data[..base_len + len],
1502                            None,
1503                            Some((SliceError::Len(err.clone()), Layer::UdpHeader)),
1504                        );
1505                    }
1506                }
1507            }
1508
1509            // tcp
1510            {
1511                let tcp = TcpHeader::new(1, 2, 3, 4);
1512                let mut test = base.clone();
1513                test.net = Some({
1514                    let mut ip = match ip {
1515                        NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1516                        NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1517                        NetHeaders::Arp(_) => unreachable!(),
1518                    };
1519                    ip.set_next_headers(ip_number::TCP);
1520                    ip.into()
1521                });
1522                test.transport = Some(TransportHeader::Tcp(tcp.clone()));
1523                test.set_payload_len(0);
1524
1525                // ok decode
1526                from_x_slice_assert_ok(&test);
1527
1528                // error can only occur if ip does not fragment the packet
1529                if false == test.is_ip_payload_fragmented() {
1530                    // length error
1531                    {
1532                        for len in 0..(tcp.header_len() as usize) {
1533                            // set payload length
1534                            let mut test = test.clone();
1535                            test.set_payload_len_ip(len as isize);
1536
1537                            let data = test.to_vec(&[]);
1538                            let base_len = test.len(&[]) - (tcp.header_len() as usize);
1539
1540                            let err = LenError {
1541                                required_len: tcp.header_len() as usize,
1542                                len,
1543                                len_source: match test.net.as_ref().unwrap() {
1544                                    NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1545                                    NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1546                                    NetHeaders::Arp(_) => unreachable!(),
1547                                },
1548                                layer: Layer::TcpHeader,
1549                                layer_start_offset: base_len,
1550                            };
1551                            assert_test_result(
1552                                &test,
1553                                &[],
1554                                &data[..base_len + len],
1555                                None,
1556                                Some((SliceError::Len(err.clone()), Layer::TcpHeader)),
1557                            );
1558                        }
1559                    }
1560
1561                    // content error
1562                    {
1563                        let mut data = test.to_vec(&[]);
1564                        let base_len = test.len(&[]) - (tcp.header_len() as usize);
1565
1566                        // set data offset to 0 to trigger an error
1567                        data[base_len + 12] = data[base_len + 12] & 0b0000_1111;
1568
1569                        let err = err::tcp::HeaderError::DataOffsetTooSmall { data_offset: 0 };
1570                        assert_test_result(
1571                            &test,
1572                            &[],
1573                            &data,
1574                            None,
1575                            Some((SliceError::Tcp(err.clone()), Layer::TcpHeader)),
1576                        );
1577                    }
1578                }
1579            }
1580
1581            // icmpv4
1582            {
1583                let icmpv4 =
1584                    Icmpv4Header::new(Icmpv4Type::EchoReply(IcmpEchoHeader { id: 1, seq: 2 }));
1585                let mut test = base.clone();
1586                test.net = Some({
1587                    let mut ip = match ip {
1588                        NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1589                        NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1590                        NetHeaders::Arp(_) => unreachable!(),
1591                    };
1592                    ip.set_next_headers(ip_number::ICMP);
1593                    ip.into()
1594                });
1595                test.transport = Some(TransportHeader::Icmpv4(icmpv4.clone()));
1596                test.set_payload_len(0);
1597
1598                // ok decode
1599                from_x_slice_assert_ok(&test);
1600
1601                // length error
1602                if false == test.is_ip_payload_fragmented() {
1603                    for len in 0..icmpv4.header_len() {
1604                        // set payload length
1605                        let mut test = test.clone();
1606                        test.set_payload_len_ip(len as isize);
1607
1608                        let data = test.to_vec(&[]);
1609                        let base_len = test.len(&[]) - icmpv4.header_len();
1610
1611                        let err = LenError {
1612                            required_len: icmpv4.header_len(),
1613                            len,
1614                            len_source: match test.net.as_ref().unwrap() {
1615                                NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1616                                NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1617                                NetHeaders::Arp(_) => unreachable!(),
1618                            },
1619                            layer: Layer::Icmpv4,
1620                            layer_start_offset: base_len,
1621                        };
1622                        assert_test_result(
1623                            &test,
1624                            &[],
1625                            &data[..base_len + len],
1626                            None,
1627                            Some((SliceError::Len(err.clone()), Layer::Icmpv4)),
1628                        );
1629                    }
1630                }
1631            }
1632
1633            // icmpv6
1634            {
1635                let icmpv6 =
1636                    Icmpv6Header::new(Icmpv6Type::EchoReply(IcmpEchoHeader { id: 1, seq: 2 }));
1637                let mut test = base.clone();
1638                test.net = Some({
1639                    let mut ip = match ip {
1640                        NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1641                        NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1642                        NetHeaders::Arp(_) => unreachable!(),
1643                    };
1644                    ip.set_next_headers(ip_number::IPV6_ICMP);
1645                    ip.into()
1646                });
1647                test.transport = Some(TransportHeader::Icmpv6(icmpv6.clone()));
1648                test.set_payload_len(0);
1649
1650                // ok decode
1651                from_x_slice_assert_ok(&test);
1652
1653                // length error
1654                if false == test.is_ip_payload_fragmented() {
1655                    for len in 0..icmpv6.header_len() {
1656                        // set payload length
1657                        let mut test = test.clone();
1658                        test.set_payload_len_ip(len as isize);
1659
1660                        let data = test.to_vec(&[]);
1661                        let base_len = test.len(&[]) - icmpv6.header_len();
1662
1663                        let err = LenError {
1664                            required_len: icmpv6.header_len(),
1665                            len,
1666                            len_source: match test.net.as_ref().unwrap() {
1667                                NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1668                                NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1669                                NetHeaders::Arp(_) => unreachable!(),
1670                            },
1671                            layer: Layer::Icmpv6,
1672                            layer_start_offset: base_len,
1673                        };
1674                        assert_test_result(
1675                            &test,
1676                            &[],
1677                            &data[..base_len + len],
1678                            None,
1679                            Some((SliceError::Len(err.clone()), Layer::Icmpv6)),
1680                        );
1681                    }
1682                }
1683            }
1684        }
1685    }
1686
1687    fn from_x_slice_assert_ok(test_base: &TestPacket) {
1688        // setup payload
1689        let payload = [1, 2, 3, 4];
1690
1691        // set length fields in ip headers
1692        let test = {
1693            let mut test = test_base.clone();
1694            test.set_payload_len(payload.len());
1695            test
1696        };
1697
1698        // write data
1699        let data = test.to_vec(&payload);
1700        assert_test_result(&test, &payload, &data, None, None);
1701    }
1702
1703    /// Check that the given output & errors (if present) are generated based on the given
1704    /// input.
1705    fn assert_test_result(
1706        test: &TestPacket,
1707        expected_payload: &[u8],
1708        data: &[u8],
1709        expected_ip_err: Option<err::ip::LaxHeaderSliceError>,
1710        expected_stop_err: Option<(SliceError, Layer)>,
1711    ) {
1712        fn compare_link_exts(test: &TestPacket, data: &[u8], actual: &LaxSlicedPacket) {
1713            let mut next_offset = if let Some(e) = test.link.as_ref() {
1714                e.header_len()
1715            } else {
1716                0
1717            };
1718            let mut expected = ArrayVec::<LinkExtHeader, 3>::new();
1719            for e in &test.link_exts {
1720                match &e {
1721                    LinkExtHeader::Vlan(s) => {
1722                        if data.len() >= next_offset + s.header_len() {
1723                            expected.push(e.clone());
1724                            next_offset += s.header_len();
1725                        } else {
1726                            break;
1727                        }
1728                    }
1729                    LinkExtHeader::Macsec(m) => {
1730                        if data.len() >= next_offset + m.header_len() {
1731                            expected.push(e.clone());
1732                            next_offset += m.header_len();
1733                        } else {
1734                            break;
1735                        }
1736                    }
1737                }
1738            }
1739            assert_eq!(
1740                expected,
1741                actual
1742                    .link_exts
1743                    .as_ref()
1744                    .iter()
1745                    .map(|v| v.to_header())
1746                    .collect::<ArrayVec<LinkExtHeader, 3>>()
1747            );
1748        }
1749
1750        fn compare_ip(test: &TestPacket, actual: &LaxSlicedPacket) {
1751            assert_eq!(
1752                test.net,
1753                actual.net.as_ref().map(|s| -> NetHeaders {
1754                    match s {
1755                        LaxNetSlice::Ipv4(ipv4) => NetHeaders::Ipv4(
1756                            ipv4.header().to_header(),
1757                            ipv4.extensions().to_header(),
1758                        ),
1759                        LaxNetSlice::Ipv6(ipv6) => NetHeaders::Ipv6(
1760                            ipv6.header().to_header(),
1761                            Ipv6Extensions::from_slice(
1762                                ipv6.header().next_header(),
1763                                ipv6.extensions().slice(),
1764                            )
1765                            .unwrap()
1766                            .0,
1767                        ),
1768                        LaxNetSlice::Arp(arp) => NetHeaders::Arp(arp.to_packet()),
1769                    }
1770                })
1771            );
1772        }
1773
1774        fn compare_net_header_only(test: &TestPacket, actual: &LaxSlicedPacket) {
1775            assert_eq!(
1776                test.net.as_ref().map(|s| -> NetHeaders {
1777                    match s {
1778                        NetHeaders::Ipv4(h, _) => NetHeaders::Ipv4(h.clone(), Default::default()),
1779                        NetHeaders::Ipv6(h, _) => NetHeaders::Ipv6(h.clone(), Default::default()),
1780                        NetHeaders::Arp(h) => NetHeaders::Arp(h.clone()),
1781                    }
1782                }),
1783                actual.net.as_ref().map(|s| -> NetHeaders {
1784                    match s {
1785                        LaxNetSlice::Ipv4(ipv4) => {
1786                            NetHeaders::Ipv4(ipv4.header().to_header(), Default::default())
1787                        }
1788                        LaxNetSlice::Ipv6(ipv6) => {
1789                            NetHeaders::Ipv6(ipv6.header().to_header(), Default::default())
1790                        }
1791                        LaxNetSlice::Arp(arp) => NetHeaders::Arp(arp.to_packet()),
1792                    }
1793                })
1794            );
1795        }
1796
1797        fn compare_transport(
1798            test: &TestPacket,
1799            is_fragmented: bool,
1800            expected_payload: &[u8],
1801            actual: &LaxSlicedPacket,
1802        ) {
1803            if is_fragmented {
1804                assert_eq!(actual.transport, None);
1805            } else {
1806                use TransportHeader as H;
1807                use TransportSlice as S;
1808                match &actual.transport {
1809                    Some(S::Icmpv4(icmpv4)) => {
1810                        assert_eq!(&test.transport, &Some(H::Icmpv4(icmpv4.header())));
1811                        assert_eq!(icmpv4.payload(), expected_payload);
1812                    }
1813                    Some(S::Icmpv6(icmpv6)) => {
1814                        assert_eq!(&test.transport, &Some(H::Icmpv6(icmpv6.header())));
1815                        assert_eq!(icmpv6.payload(), expected_payload);
1816                    }
1817                    Some(S::Udp(s)) => {
1818                        assert_eq!(&test.transport, &Some(H::Udp(s.to_header())));
1819                    }
1820                    Some(S::Tcp(s)) => {
1821                        assert_eq!(&test.transport, &Some(H::Tcp(s.to_header())));
1822                    }
1823                    None => {
1824                        assert_eq!(&test.transport, &None);
1825                    }
1826                }
1827            }
1828        }
1829
1830        // from_ethernet_slice
1831        if test.link.is_some() {
1832            if data.len() < Ethernet2Header::LEN {
1833                assert_eq!(
1834                    LenError {
1835                        required_len: Ethernet2Header::LEN,
1836                        len: data.len(),
1837                        len_source: LenSource::Slice,
1838                        layer: Layer::Ethernet2Header,
1839                        layer_start_offset: 0
1840                    },
1841                    LaxSlicedPacket::from_ethernet(&data).unwrap_err()
1842                );
1843            } else {
1844                let actual = LaxSlicedPacket::from_ethernet(&data).unwrap();
1845                assert_eq!(actual.stop_err, expected_stop_err);
1846                match expected_stop_err.as_ref().map(|v| v.1) {
1847                    None => {
1848                        assert_eq!(
1849                            test.link,
1850                            actual.link.as_ref().map(|v| v.to_header()).flatten()
1851                        );
1852                        compare_link_exts(test, data, &actual);
1853                        compare_ip(test, &actual);
1854                        compare_transport(
1855                            test,
1856                            test.is_ip_payload_fragmented(),
1857                            expected_payload,
1858                            &actual,
1859                        );
1860                    }
1861                    Some(Layer::VlanHeader) | Some(Layer::MacsecHeader) => {
1862                        assert_eq!(
1863                            test.link,
1864                            actual.link.as_ref().map(|v| v.to_header()).flatten()
1865                        );
1866                        compare_link_exts(test, data, &actual);
1867                        assert_eq!(None, actual.net);
1868                        assert_eq!(None, actual.transport);
1869                    }
1870                    Some(Layer::Ipv6Header)
1871                    | Some(Layer::Ipv4Header)
1872                    | Some(Layer::IpHeader)
1873                    | Some(Layer::Arp) => {
1874                        assert_eq!(
1875                            test.link,
1876                            actual.link.as_ref().map(|v| v.to_header()).flatten()
1877                        );
1878                        compare_link_exts(test, data, &actual);
1879                        assert_eq!(None, actual.net);
1880                        assert_eq!(None, actual.transport);
1881                    }
1882                    Some(Layer::IpAuthHeader)
1883                    | Some(Layer::Ipv6ExtHeader)
1884                    | Some(Layer::Ipv6HopByHopHeader)
1885                    | Some(Layer::Ipv6DestOptionsHeader)
1886                    | Some(Layer::Ipv6RouteHeader)
1887                    | Some(Layer::Ipv6FragHeader) => {
1888                        assert_eq!(
1889                            test.link,
1890                            actual.link.as_ref().map(|v| v.to_header()).flatten()
1891                        );
1892                        compare_link_exts(test, data, &actual);
1893                        compare_net_header_only(test, &actual);
1894                        assert_eq!(None, actual.transport);
1895                    }
1896                    Some(Layer::TcpHeader)
1897                    | Some(Layer::UdpHeader)
1898                    | Some(Layer::Icmpv4)
1899                    | Some(Layer::Icmpv6) => {
1900                        assert_eq!(
1901                            test.link,
1902                            actual.link.as_ref().map(|v| v.to_header()).flatten()
1903                        );
1904                        compare_link_exts(test, data, &actual);
1905                        compare_ip(test, &actual);
1906                        assert_eq!(None, actual.transport);
1907                    }
1908                    _ => unreachable!("error in an unexpected layer"),
1909                }
1910            }
1911        }
1912        // from_ether_type (vlan at start)
1913        if test.link.is_none() && !test.link_exts.is_empty() {
1914            let ether_types: &[EtherType] = match test.link_exts.first().unwrap() {
1915                LinkExtHeader::Vlan(_) => &VLAN_ETHER_TYPES,
1916                LinkExtHeader::Macsec(_) => &MACSEC_ETHER_TYPES,
1917            };
1918            for ether_type in ether_types {
1919                let actual = LaxSlicedPacket::from_ether_type(*ether_type, data);
1920                assert_eq!(actual.stop_err, expected_stop_err);
1921                assert_eq!(
1922                    Some(LinkSlice::EtherPayload(EtherPayloadSlice {
1923                        ether_type: *ether_type,
1924                        len_source: LenSource::Slice,
1925                        payload: data
1926                    })),
1927                    actual.link
1928                );
1929                compare_link_exts(test, data, &actual);
1930                match expected_stop_err.as_ref().map(|v| v.1) {
1931                    None => {
1932                        compare_ip(test, &actual);
1933                        compare_transport(
1934                            test,
1935                            test.is_ip_payload_fragmented(),
1936                            expected_payload,
1937                            &actual,
1938                        );
1939                    }
1940                    Some(Layer::VlanHeader) | Some(Layer::MacsecHeader) => {
1941                        assert_eq!(None, actual.net);
1942                        assert_eq!(None, actual.transport);
1943                    }
1944                    Some(Layer::Ipv6Header)
1945                    | Some(Layer::Ipv4Header)
1946                    | Some(Layer::IpHeader)
1947                    | Some(Layer::Arp) => {
1948                        assert_eq!(None, actual.net);
1949                        assert_eq!(None, actual.transport);
1950                    }
1951                    Some(Layer::IpAuthHeader)
1952                    | Some(Layer::Ipv6ExtHeader)
1953                    | Some(Layer::Ipv6HopByHopHeader)
1954                    | Some(Layer::Ipv6DestOptionsHeader)
1955                    | Some(Layer::Ipv6RouteHeader)
1956                    | Some(Layer::Ipv6FragHeader) => {
1957                        compare_net_header_only(test, &actual);
1958                        assert_eq!(None, actual.transport);
1959                    }
1960                    Some(Layer::TcpHeader)
1961                    | Some(Layer::UdpHeader)
1962                    | Some(Layer::Icmpv4)
1963                    | Some(Layer::Icmpv6) => {
1964                        compare_ip(test, &actual);
1965                        assert_eq!(None, actual.transport);
1966                    }
1967                    _ => unreachable!("error in an unexpected layer"),
1968                }
1969            }
1970        }
1971        // from_ether_type (net at start)
1972        if test.link.is_none() && test.link_exts.is_empty() {
1973            if let Some(ip) = &test.net {
1974                let ether_type = match ip {
1975                    NetHeaders::Ipv4(_, _) => ether_type::IPV4,
1976                    NetHeaders::Ipv6(_, _) => ether_type::IPV6,
1977                    NetHeaders::Arp(_) => ether_type::ARP,
1978                };
1979                let actual = LaxSlicedPacket::from_ether_type(ether_type, &data);
1980                assert_eq!(actual.stop_err, expected_stop_err);
1981                assert_eq!(
1982                    Some(LinkSlice::EtherPayload(EtherPayloadSlice {
1983                        ether_type,
1984                        len_source: LenSource::Slice,
1985                        payload: data
1986                    })),
1987                    actual.link
1988                );
1989                assert!(actual.link_exts.is_empty());
1990                match expected_stop_err.as_ref().map(|v| v.1) {
1991                    None => {
1992                        compare_ip(test, &actual);
1993                        compare_transport(
1994                            test,
1995                            test.is_ip_payload_fragmented(),
1996                            expected_payload,
1997                            &actual,
1998                        );
1999                    }
2000                    Some(Layer::Ipv6Header)
2001                    | Some(Layer::Ipv4Header)
2002                    | Some(Layer::IpHeader)
2003                    | Some(Layer::Arp) => {
2004                        assert_eq!(None, actual.net);
2005                        assert_eq!(None, actual.transport);
2006                    }
2007                    Some(Layer::IpAuthHeader)
2008                    | Some(Layer::Ipv6ExtHeader)
2009                    | Some(Layer::Ipv6HopByHopHeader)
2010                    | Some(Layer::Ipv6DestOptionsHeader)
2011                    | Some(Layer::Ipv6RouteHeader)
2012                    | Some(Layer::Ipv6FragHeader) => {
2013                        compare_net_header_only(test, &actual);
2014                        assert_eq!(None, actual.transport);
2015                    }
2016                    Some(Layer::TcpHeader)
2017                    | Some(Layer::UdpHeader)
2018                    | Some(Layer::Icmpv4)
2019                    | Some(Layer::Icmpv6) => {
2020                        compare_ip(test, &actual);
2021                        assert_eq!(None, actual.transport);
2022                    }
2023                    _ => unreachable!("error in an unexpected layer"),
2024                }
2025            }
2026        }
2027        // from_ip_slice
2028        if test.link.is_none()
2029            && test.link_exts.is_empty()
2030            && matches!(
2031                test.net,
2032                Some(NetHeaders::Ipv4(_, _)) | Some(NetHeaders::Ipv6(_, _))
2033            )
2034        {
2035            if let Some(err) = expected_ip_err {
2036                assert_eq!(err, LaxSlicedPacket::from_ip(&data).unwrap_err());
2037            } else {
2038                let actual = LaxSlicedPacket::from_ip(&data).unwrap();
2039                assert_eq!(actual.stop_err, expected_stop_err);
2040                assert_eq!(actual.link, None);
2041                assert!(actual.link_exts.is_empty());
2042                match expected_stop_err.as_ref().map(|v| v.1) {
2043                    None => {
2044                        compare_ip(test, &actual);
2045                        compare_transport(
2046                            test,
2047                            test.is_ip_payload_fragmented(),
2048                            expected_payload,
2049                            &actual,
2050                        );
2051                    }
2052                    Some(Layer::IpAuthHeader)
2053                    | Some(Layer::Ipv6ExtHeader)
2054                    | Some(Layer::Ipv6HopByHopHeader)
2055                    | Some(Layer::Ipv6DestOptionsHeader)
2056                    | Some(Layer::Ipv6RouteHeader)
2057                    | Some(Layer::Ipv6FragHeader) => {
2058                        compare_net_header_only(test, &actual);
2059                        assert_eq!(None, actual.transport);
2060                    }
2061                    Some(Layer::TcpHeader)
2062                    | Some(Layer::UdpHeader)
2063                    | Some(Layer::Icmpv4)
2064                    | Some(Layer::Icmpv6) => {
2065                        compare_ip(test, &actual);
2066                        assert_eq!(None, actual.transport);
2067                    }
2068                    _ => unreachable!("error in an unexpected layer"),
2069                }
2070            }
2071        }
2072    }
2073}