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