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