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

etherparse/
lax_packet_headers.rs

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