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