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

etherparse/
packet_headers.rs

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