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

etherparse/
sliced_packet.rs

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