1 use crate::err::LenError;
2 
3 use super::*;
4 
5 /// Decoded packet headers (data link layer and lower).
6 ///
7 /// You can use
8 ///
9 /// * [`PacketHeaders::from_ethernet_slice`]
10 /// * [`PacketHeaders::from_ether_type`]
11 /// * [`PacketHeaders::from_ip_slice`]
12 ///
13 /// depending on your starting header to parse the headers in a slice and get this
14 /// struct as a result.
15 #[derive(Clone, Debug, Eq, PartialEq)]
16 pub struct PacketHeaders<'a> {
17     /// Ethernet II header if present.
18     pub link: Option<LinkHeader>,
19     /// Single or double vlan headers if present.
20     pub vlan: Option<VlanHeader>,
21     /// IPv4 or IPv6 header and IP extension headers if present.
22     pub net: Option<NetHeaders>,
23     /// TCP or UDP header if present.
24     pub transport: Option<TransportHeader>,
25     /// Payload of the last parsed layer.
26     pub payload: PayloadSlice<'a>,
27 }
28 
29 impl<'a> PacketHeaders<'a> {
30     /// Decodes a network packet into different headers from a slice that starts with an Ethernet II header.
31     ///
32     /// The result is returned as a [`PacketHeaders`] struct.
33     ///
34     /// # Example
35     ///
36     /// Basic usage:
37     ///
38     ///```
39     /// # use etherparse::{Ethernet2Header, PacketBuilder};
40     /// # let builder = PacketBuilder::
41     /// #    ethernet2([1,2,3,4,5,6],     //source mac
42     /// #               [7,8,9,10,11,12]) //destination mac
43     /// #    .ipv4([192,168,1,1], //source ip
44     /// #          [192,168,1,2], //destination ip
45     /// #          20)            //time to life
46     /// #    .udp(21,    //source port
47     /// #         1234); // destination port
48     /// # // payload of the udp packet
49     /// # let payload = [1,2,3,4,5,6,7,8];
50     /// # // get some memory to store the serialized data
51     /// # let mut complete_packet = Vec::<u8>::with_capacity(
52     /// #     builder.size(payload.len())
53     /// # );
54     /// # builder.write(&mut complete_packet, &payload).unwrap();
55     /// #
56     /// # // skip ethernet 2 header so we can parse from there downwards
57     /// # let packet = &complete_packet[Ethernet2Header::LEN..];
58     /// #
59     /// use etherparse::{ether_type, PacketHeaders};
60     ///
61     /// match PacketHeaders::from_ether_type(ether_type::IPV4, packet) {
62     ///     Err(value) => println!("Err {:?}", value),
63     ///     Ok(value) => {
64     ///         println!("link: {:?}", value.link);
65     ///         println!("vlan: {:?}", value.vlan);
66     ///         println!("net: {:?}", value.net);
67     ///         println!("transport: {:?}", value.transport);
68     ///     }
69     /// }
70     /// ```
from_ethernet_slice( slice: &'a [u8], ) -> Result<PacketHeaders<'a>, err::packet::SliceError>71     pub fn from_ethernet_slice(
72         slice: &'a [u8],
73     ) -> Result<PacketHeaders<'a>, err::packet::SliceError> {
74         use err::packet::SliceError::Len;
75 
76         let (ethernet, rest) = Ethernet2Header::from_slice(slice).map_err(Len)?;
77         let mut result = Self::from_ether_type(ethernet.ether_type, rest);
78 
79         match &mut result {
80             // inject ethernet header into the result
81             Ok(result) => result.link = Some(LinkHeader::Ethernet2(ethernet)),
82             // add the ethernet header to the overall offset in case there is a length error
83             Err(Len(err)) => err.layer_start_offset += Ethernet2Header::LEN,
84             _ => {}
85         }
86         result
87     }
88 
89     /// Tries to decode a network packet into different headers using the
90     /// given `ether_type` number to identify the first header.
91     ///
92     /// The result is returned as a [`PacketHeaders`] struct. Currently supported
93     /// ether type numbers are:
94     ///
95     /// * `ether_type::IPV4`
96     /// * `ether_type::IPV6`
97     /// * `ether_type::VLAN_TAGGED_FRAME`
98     /// * `ether_type::PROVIDER_BRIDGING`
99     /// * `ether_type::VLAN_DOUBLE_TAGGED_FRAME`
100     ///
101     /// If an unsupported ether type is given the given slice will be set as payload
102     /// and all other fields will be set to `None`.
103     ///
104     /// # Example
105     ///
106     /// Basic usage:
107     ///
108     ///```
109     /// # use etherparse::{Ethernet2Header, PacketBuilder};
110     /// # let builder = PacketBuilder::
111     /// #    ethernet2([1,2,3,4,5,6],     //source mac
112     /// #               [7,8,9,10,11,12]) //destination mac
113     /// #    .ipv4([192,168,1,1], //source ip
114     /// #          [192,168,1,2], //destination ip
115     /// #          20)            //time to life
116     /// #    .udp(21,    //source port
117     /// #         1234); // destination port
118     /// # // payload of the udp packet
119     /// # let payload = [1,2,3,4,5,6,7,8];
120     /// # // get some memory to store the serialized data
121     /// # let mut complete_packet = Vec::<u8>::with_capacity(
122     /// #     builder.size(payload.len())
123     /// # );
124     /// # builder.write(&mut complete_packet, &payload).unwrap();
125     /// #
126     /// # // skip ethernet 2 header so we can parse from there downwards
127     /// # let packet = &complete_packet[Ethernet2Header::LEN..];
128     /// #
129     /// use etherparse::{ether_type, PacketHeaders};
130     ///
131     /// match PacketHeaders::from_ether_type(ether_type::IPV4, packet) {
132     ///     Err(value) => println!("Err {:?}", value),
133     ///     Ok(value) => {
134     ///         println!("link: {:?}", value.link);
135     ///         println!("vlan: {:?}", value.vlan);
136     ///         println!("net: {:?}", value.net);
137     ///         println!("transport: {:?}", value.transport);
138     ///     }
139     /// }
140     /// ```
from_ether_type( mut ether_type: EtherType, slice: &'a [u8], ) -> Result<PacketHeaders<'a>, err::packet::SliceError>141     pub fn from_ether_type(
142         mut ether_type: EtherType,
143         slice: &'a [u8],
144     ) -> Result<PacketHeaders<'a>, err::packet::SliceError> {
145         use err::packet::SliceError::*;
146 
147         let mut rest = slice;
148 
149         // helper function to add the current offset to length errors
150         let add_offset = |mut len_error: LenError, rest: &[u8]| -> LenError {
151             len_error.layer_start_offset += unsafe {
152                 // SAFETY: Safe as rest is a subslice of slice.
153                 rest.as_ptr().offset_from(slice.as_ptr()) as usize
154             };
155             len_error
156         };
157 
158         let mut result = PacketHeaders {
159             link: None,
160             vlan: None,
161             net: None,
162             transport: None,
163             payload: PayloadSlice::Ether(EtherPayloadSlice {
164                 ether_type,
165                 payload: rest,
166             }),
167         };
168 
169         //parse vlan header(s)
170         use ether_type::*;
171 
172         result.vlan = match ether_type {
173             VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => {
174                 use crate::VlanHeader::*;
175                 let (outer, outer_rest) = SingleVlanHeader::from_slice(rest).map_err(Len)?;
176 
177                 //set the rest & ether_type for the following operations
178                 rest = outer_rest;
179                 ether_type = outer.ether_type;
180                 result.payload = PayloadSlice::Ether(EtherPayloadSlice {
181                     ether_type,
182                     payload: rest,
183                 });
184 
185                 //parse second vlan header if present
186                 match ether_type {
187                     //second vlan tagging header
188                     VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => {
189                         let (inner, inner_rest) = SingleVlanHeader::from_slice(rest)
190                             .map_err(|err| Len(err.add_offset(SingleVlanHeader::LEN)))?;
191 
192                         //set the rest & ether_type for the following operations
193                         rest = inner_rest;
194                         ether_type = inner.ether_type;
195                         result.payload = PayloadSlice::Ether(EtherPayloadSlice {
196                             ether_type,
197                             payload: rest,
198                         });
199 
200                         Some(Double(DoubleVlanHeader { outer, inner }))
201                     }
202                     //no second vlan header detected -> single vlan header
203                     _ => Some(Single(outer)),
204                 }
205             }
206             //no vlan header
207             _ => None,
208         };
209 
210         // parse ip
211         match ether_type {
212             IPV4 => {
213                 // read ipv4 header & extensions and payload slice
214                 let (ip, ip_payload) = IpHeaders::from_ipv4_slice(rest).map_err(|err| {
215                     use err::ipv4::SliceError as I;
216                     match err {
217                         I::Len(err) => Len(add_offset(err, rest)),
218                         I::Header(err) => Ipv4(err),
219                         I::Exts(err) => Ipv4Exts(err),
220                     }
221                 })?;
222 
223                 // set the next
224                 rest = ip_payload.payload;
225                 result.net = Some(ip.into());
226                 result.payload = PayloadSlice::Ip(ip_payload.clone());
227 
228                 // decode transport layer
229                 let (transport, payload) = read_transport(ip_payload).map_err(|err| {
230                     use err::tcp::HeaderSliceError as I;
231                     match err {
232                         I::Len(err) => Len(add_offset(err, rest)),
233                         I::Content(err) => Tcp(err),
234                     }
235                 })?;
236 
237                 result.transport = transport;
238                 result.payload = payload;
239             }
240             IPV6 => {
241                 // read ipv6 header & extensions and payload slice
242                 let (ip, ip_payload) = IpHeaders::from_ipv6_slice(rest).map_err(|err| {
243                     use err::ipv6::SliceError as I;
244                     match err {
245                         I::Len(err) => Len(add_offset(err, rest)),
246                         I::Header(err) => Ipv6(err),
247                         I::Exts(err) => Ipv6Exts(err),
248                     }
249                 })?;
250 
251                 //set the ip result & rest
252                 rest = ip_payload.payload;
253                 result.net = Some(ip.into());
254                 result.payload = PayloadSlice::Ip(ip_payload.clone());
255 
256                 // decode transport layer
257                 let (transport, payload) = read_transport(ip_payload).map_err(|err| {
258                     use err::tcp::HeaderSliceError as I;
259                     match err {
260                         I::Len(err) => Len(add_offset(err, rest)),
261                         I::Content(err) => Tcp(err),
262                     }
263                 })?;
264 
265                 result.transport = transport;
266                 result.payload = payload;
267             }
268             _ => {}
269         };
270 
271         Ok(result)
272     }
273 
274     /// Tries to decode an ip packet and its transport headers.
275     ///
276     /// Assumes the given slice starts with the first byte of the IP header.
277     ///
278     /// # Example
279     ///
280     /// Basic usage:
281     ///
282     /// ```
283     /// # use etherparse::PacketBuilder;
284     /// # // build a UDP packet
285     /// # let payload = [0u8;18];
286     /// # let builder = PacketBuilder::
287     /// #    ipv4([192,168,1,1], //source ip
288     /// #         [192,168,1,2], //destination ip
289     /// #         20)            //time to life
290     /// #    .udp(21,    //source port
291     /// #        1234); //  destination port
292     /// #
293     /// # // serialize the packet
294     /// # let packet = {
295     /// #     let mut packet = Vec::<u8>::with_capacity(
296     /// #         builder.size(payload.len())
297     /// #     );
298     /// #     builder.write(&mut packet, &payload).unwrap();
299     /// #     packet
300     /// # };
301     /// use etherparse::PacketHeaders;
302     ///
303     /// match PacketHeaders::from_ip_slice(&packet) {
304     ///     Err(value) => println!("Err {:?}", value),
305     ///     Ok(value) => {
306     ///         println!("link: {:?}", value.link);
307     ///         println!("vlan: {:?}", value.vlan);
308     ///         println!("net: {:?}", value.net);
309     ///         println!("transport: {:?}", value.transport);
310     ///     }
311     /// }
312     /// ```
from_ip_slice(slice: &[u8]) -> Result<PacketHeaders, err::packet::SliceError>313     pub fn from_ip_slice(slice: &[u8]) -> Result<PacketHeaders, err::packet::SliceError> {
314         use err::packet::SliceError::*;
315 
316         // read ip headers
317         let (ip_header, ip_payload) = IpHeaders::from_slice(slice).map_err(|err| {
318             use err::ip::HeadersSliceError as I;
319             match err {
320                 I::Len(err) => Len(err),
321                 I::Content(err) => match err {
322                     err::ip::HeadersError::Ip(err) => Ip(err),
323                     err::ip::HeadersError::Ipv4Ext(err) => Ipv4Exts(err),
324                     err::ip::HeadersError::Ipv6Ext(err) => Ipv6Exts(err),
325                 },
326             }
327         })?;
328 
329         let mut result = PacketHeaders {
330             link: None,
331             vlan: None,
332             net: Some(ip_header.into()),
333             transport: None,
334             payload: PayloadSlice::Ip(ip_payload.clone()),
335         };
336 
337         // cache rest for offset addition
338         let rest = ip_payload.payload;
339 
340         // try to parse the transport header (only if data is not fragmented)
341         let (transport, payload) = read_transport(ip_payload).map_err(|err| {
342             use err::tcp::HeaderSliceError as I;
343             match err {
344                 I::Len(mut err) => {
345                     err.layer_start_offset += unsafe {
346                         // SAFETY: Safe as rest is a subslice of slice.
347                         rest.as_ptr().offset_from(slice.as_ptr()) as usize
348                     };
349                     Len(err)
350                 }
351                 I::Content(err) => Tcp(err),
352             }
353         })?;
354 
355         // update output
356         result.transport = transport;
357         result.payload = payload;
358 
359         Ok(result)
360     }
361 }
362 
363 /// helper function to process transport headers
read_transport( ip_payload: IpPayloadSlice, ) -> Result<(Option<TransportHeader>, PayloadSlice), err::tcp::HeaderSliceError>364 fn read_transport(
365     ip_payload: IpPayloadSlice,
366 ) -> Result<(Option<TransportHeader>, PayloadSlice), err::tcp::HeaderSliceError> {
367     if ip_payload.fragmented {
368         Ok((None, PayloadSlice::Ip(ip_payload)))
369     } else {
370         // helper function to set the len source in len errors
371         let add_len_source = |mut len_error: LenError| -> err::tcp::HeaderSliceError {
372             // only change the len source if the lower layer has not set it
373             if LenSource::Slice == len_error.len_source {
374                 len_error.len_source = ip_payload.len_source;
375             }
376             Len(len_error)
377         };
378         use crate::ip_number::*;
379         use err::tcp::HeaderSliceError::*;
380         match ip_payload.ip_number {
381             ICMP => Icmpv4Slice::from_slice(ip_payload.payload)
382                 .map_err(add_len_source)
383                 .map(|value| {
384                     (
385                         Some(TransportHeader::Icmpv4(value.header())),
386                         PayloadSlice::Icmpv4(value.payload()),
387                     )
388                 }),
389             IPV6_ICMP => Icmpv6Slice::from_slice(ip_payload.payload)
390                 .map_err(add_len_source)
391                 .map(|value| {
392                     (
393                         Some(TransportHeader::Icmpv6(value.header())),
394                         PayloadSlice::Icmpv6(value.payload()),
395                     )
396                 }),
397             UDP => UdpHeader::from_slice(ip_payload.payload)
398                 .map_err(add_len_source)
399                 .map(|value| {
400                     (
401                         Some(TransportHeader::Udp(value.0)),
402                         PayloadSlice::Udp(value.1),
403                     )
404                 }),
405             TCP => TcpHeader::from_slice(ip_payload.payload)
406                 .map_err(|err| match err {
407                     Len(err) => add_len_source(err),
408                     Content(err) => Content(err),
409                 })
410                 .map(|value| {
411                     (
412                         Some(TransportHeader::Tcp(value.0)),
413                         PayloadSlice::Tcp(value.1),
414                     )
415                 }),
416             _ => Ok((None, PayloadSlice::Ip(ip_payload))),
417         }
418     }
419 }
420 
421 #[cfg(test)]
422 mod test {
423     use super::*;
424     use crate::err::packet::SliceError;
425     use crate::test_packet::TestPacket;
426 
427     const VLAN_ETHER_TYPES: [EtherType; 3] = [
428         ether_type::VLAN_TAGGED_FRAME,
429         ether_type::PROVIDER_BRIDGING,
430         ether_type::VLAN_DOUBLE_TAGGED_FRAME,
431     ];
432 
433     #[test]
debug()434     fn debug() {
435         use alloc::format;
436         let header = PacketHeaders {
437             link: None,
438             vlan: None,
439             net: None,
440             transport: None,
441             payload: PayloadSlice::Ether(EtherPayloadSlice {
442                 ether_type: EtherType(0),
443                 payload: &[],
444             }),
445         };
446         assert_eq!(
447             &format!("{:?}", header),
448             &format!(
449                 "PacketHeaders {{ link: {:?}, vlan: {:?}, net: {:?}, transport: {:?}, payload: {:?} }}",
450                 header.link,
451                 header.vlan,
452                 header.net,
453                 header.transport,
454                 header.payload
455             )
456         );
457     }
458 
459     #[test]
clone_eq()460     fn clone_eq() {
461         let header = PacketHeaders {
462             link: None,
463             vlan: None,
464             net: None,
465             transport: None,
466             payload: PayloadSlice::Ether(EtherPayloadSlice {
467                 ether_type: EtherType(0),
468                 payload: &[],
469             }),
470         };
471         assert_eq!(header.clone(), header);
472     }
473 
474     #[test]
from_x_slice()475     fn from_x_slice() {
476         // no eth
477         from_x_slice_vlan_variants(&TestPacket {
478             link: None,
479             vlan: None,
480             net: None,
481             transport: None,
482         });
483 
484         // eth
485         {
486             let eth = Ethernet2Header {
487                 source: [1, 2, 3, 4, 5, 6],
488                 destination: [1, 2, 3, 4, 5, 6],
489                 ether_type: 0.into(),
490             };
491             let test = TestPacket {
492                 link: Some(LinkHeader::Ethernet2(eth.clone())),
493                 vlan: None,
494                 net: None,
495                 transport: None,
496             };
497 
498             // ok ethernet header (with unknown next)
499             from_x_slice_vlan_variants(&test);
500 
501             // eth len error
502             {
503                 let data = test.to_vec(&[]);
504                 for len in 0..data.len() {
505                     let err = LenError {
506                         required_len: eth.header_len(),
507                         len,
508                         len_source: LenSource::Slice,
509                         layer: err::Layer::Ethernet2Header,
510                         layer_start_offset: 0,
511                     };
512 
513                     from_slice_assert_err(&test, &data[..len], SliceError::Len(err.clone()));
514                 }
515             }
516         }
517     }
518 
from_x_slice_vlan_variants(base: &TestPacket)519     fn from_x_slice_vlan_variants(base: &TestPacket) {
520         // none
521         from_x_slice_ip_variants(base);
522 
523         // single vlan header
524         {
525             let single = SingleVlanHeader {
526                 pcp: 1.try_into().unwrap(),
527                 drop_eligible_indicator: false,
528                 vlan_id: 2.try_into().unwrap(),
529                 ether_type: 3.into(),
530             };
531 
532             for vlan_ether_type in VLAN_ETHER_TYPES {
533                 let mut test = base.clone();
534                 test.set_ether_type(vlan_ether_type);
535                 test.vlan = Some(VlanHeader::Single(single.clone()));
536 
537                 // ok vlan header
538                 from_x_slice_ip_variants(&test);
539 
540                 // len error
541                 {
542                     let data = test.to_vec(&[]);
543                     for len in 0..single.header_len() {
544                         let base_len = test.len(&[]) - single.header_len();
545 
546                         let err = LenError {
547                             required_len: single.header_len(),
548                             len,
549                             len_source: LenSource::Slice,
550                             layer: err::Layer::VlanHeader,
551                             layer_start_offset: base_len,
552                         };
553                         from_slice_assert_err(
554                             &test,
555                             &data[..base_len + len],
556                             SliceError::Len(err.clone()),
557                         );
558                     }
559                 }
560             }
561         }
562 
563         // double vlan header
564         for outer_vlan_ether_type in VLAN_ETHER_TYPES {
565             for inner_vlan_ether_type in VLAN_ETHER_TYPES {
566                 let double = DoubleVlanHeader {
567                     outer: SingleVlanHeader {
568                         pcp: 1.try_into().unwrap(),
569                         drop_eligible_indicator: false,
570                         vlan_id: 2.try_into().unwrap(),
571                         ether_type: inner_vlan_ether_type,
572                     },
573                     inner: SingleVlanHeader {
574                         pcp: 1.try_into().unwrap(),
575                         drop_eligible_indicator: false,
576                         vlan_id: 2.try_into().unwrap(),
577                         ether_type: 3.into(),
578                     },
579                 };
580                 let mut test = base.clone();
581                 test.set_ether_type(outer_vlan_ether_type);
582                 test.vlan = Some(VlanHeader::Double(double.clone()));
583 
584                 // ok double vlan header
585                 from_x_slice_ip_variants(&test);
586 
587                 // len error
588                 {
589                     let data = test.to_vec(&[]);
590                     for len in 0..SingleVlanHeader::LEN {
591                         let base_len = test.len(&[]) - SingleVlanHeader::LEN;
592 
593                         let err = LenError {
594                             required_len: SingleVlanHeader::LEN,
595                             len,
596                             len_source: LenSource::Slice,
597                             layer: err::Layer::VlanHeader,
598                             layer_start_offset: base_len,
599                         };
600                         from_slice_assert_err(
601                             &test,
602                             &data[..base_len + len],
603                             SliceError::Len(err.clone()),
604                         );
605                     }
606                 }
607             }
608         }
609     }
610 
from_x_slice_ip_variants(base: &TestPacket)611     fn from_x_slice_ip_variants(base: &TestPacket) {
612         // none
613         from_x_slice_transport_variants(base);
614 
615         // ipv4
616         for fragmented in [false, true] {
617             let ipv4 = {
618                 let mut ipv4 =
619                     Ipv4Header::new(0, 1, 2.into(), [3, 4, 5, 6], [7, 8, 9, 10]).unwrap();
620                 ipv4.more_fragments = fragmented;
621                 ipv4
622             };
623 
624             {
625                 let mut test = base.clone();
626                 test.set_ether_type(ether_type::IPV4);
627                 test.net = Some(NetHeaders::Ipv4(ipv4.clone(), Default::default()));
628 
629                 // ok ipv4
630                 from_x_slice_transport_variants(&test);
631 
632                 // ipv4 len error
633                 {
634                     let data = test.to_vec(&[]);
635                     for len in 0..ipv4.header_len() {
636                         let base_len = test.len(&[]) - ipv4.header_len();
637 
638                         let err = LenError {
639                             required_len: ipv4.header_len(),
640                             len,
641                             len_source: LenSource::Slice,
642                             layer: err::Layer::Ipv4Header,
643                             layer_start_offset: base_len,
644                         };
645                         from_slice_assert_err(
646                             &test,
647                             &data[..base_len + len],
648                             if test.link.is_some() || test.vlan.is_some() {
649                                 SliceError::Len(err.clone())
650                             } else {
651                                 SliceError::Len({
652                                     if len < 1 {
653                                         let mut err = err.clone();
654                                         err.required_len = 1;
655                                         err.layer = err::Layer::IpHeader;
656                                         err
657                                     } else {
658                                         err.clone()
659                                     }
660                                 })
661                             },
662                         );
663                     }
664                 }
665 
666                 // ipv4 content error
667                 {
668                     let mut data = test.to_vec(&[]);
669                     let ipv4_offset = data.len() - ipv4.header_len();
670 
671                     // set the ihl to 0 to trigger a content error
672                     data[ipv4_offset] = 0b1111_0000 & data[ipv4_offset];
673 
674                     from_slice_assert_err(
675                         &test,
676                         &data,
677                         if test.link.is_some() || test.vlan.is_some() {
678                             SliceError::Ipv4(
679                                 err::ipv4::HeaderError::HeaderLengthSmallerThanHeader { ihl: 0 },
680                             )
681                         } else {
682                             SliceError::Ip(
683                                 err::ip::HeaderError::Ipv4HeaderLengthSmallerThanHeader { ihl: 0 },
684                             )
685                         },
686                     );
687                 }
688             }
689 
690             // ipv4 extension content error
691             {
692                 let auth = IpAuthHeader::new(0.into(), 1, 2, &[]).unwrap();
693 
694                 let mut test = base.clone();
695                 test.set_ether_type(ether_type::IPV4);
696                 test.net = Some(NetHeaders::Ipv4(
697                     {
698                         let mut ipv4 = ipv4.clone();
699                         ipv4.protocol = ip_number::AUTH;
700                         ipv4
701                     },
702                     Ipv4Extensions {
703                         auth: Some(auth.clone()),
704                     },
705                 ));
706                 test.set_payload_len(0);
707 
708                 // ok ipv4 & extension
709                 from_x_slice_transport_variants(&test);
710 
711                 // ipv4 extension len error
712                 for len in 0..auth.header_len() {
713                     // set payload length
714                     let mut test = test.clone();
715                     test.set_payload_le_from_ip_on(
716                         -1 * (auth.header_len() as isize) + (len as isize),
717                     );
718 
719                     let data = test.to_vec(&[]);
720                     let base_len = test.len(&[]) - auth.header_len();
721 
722                     let err = LenError {
723                         required_len: auth.header_len(),
724                         len,
725                         len_source: LenSource::Ipv4HeaderTotalLen,
726                         layer: err::Layer::IpAuthHeader,
727                         layer_start_offset: base_len,
728                     };
729 
730                     from_slice_assert_err(
731                         &test,
732                         &data[..base_len + len],
733                         SliceError::Len(err.clone()),
734                     );
735                 }
736 
737                 // ipv4 extension content error
738                 {
739                     let mut data = test.to_vec(&[]);
740                     let auth_offset = data.len() - auth.header_len();
741 
742                     // set the icv len too smaller then allowed
743                     data[auth_offset + 1] = 0;
744 
745                     // expect an error
746                     let err = err::ip_auth::HeaderError::ZeroPayloadLen;
747                     from_slice_assert_err(&test, &data, SliceError::Ipv4Exts(err.clone()));
748                 }
749             }
750         }
751 
752         // ipv6
753         {
754             let ipv6 = Ipv6Header {
755                 traffic_class: 0,
756                 flow_label: 1.try_into().unwrap(),
757                 payload_length: 2,
758                 next_header: 3.into(),
759                 hop_limit: 4,
760                 source: [0; 16],
761                 destination: [0; 16],
762             };
763 
764             // ipv6 header only
765             {
766                 let mut test = base.clone();
767                 test.set_ether_type(ether_type::IPV6);
768                 test.net = Some(NetHeaders::Ipv6(ipv6.clone(), Default::default()));
769                 test.set_payload_len(0);
770 
771                 // ok ipv6
772                 from_x_slice_transport_variants(&test);
773 
774                 // header len ipv6
775                 {
776                     let data = test.to_vec(&[]);
777                     for len in 0..ipv6.header_len() {
778                         let base_len = test.len(&[]) - ipv6.header_len();
779 
780                         let err = err::LenError {
781                             required_len: ipv6.header_len(),
782                             len,
783                             len_source: LenSource::Slice,
784                             layer: err::Layer::Ipv6Header,
785                             layer_start_offset: base_len,
786                         };
787 
788                         from_slice_assert_err(
789                             &test,
790                             &data[..base_len + len],
791                             if test.link.is_some() || test.vlan.is_some() {
792                                 SliceError::Len(err.clone())
793                             } else {
794                                 SliceError::Len({
795                                     if len < 1 {
796                                         let mut err = err.clone();
797                                         err.required_len = 1;
798                                         err.layer = err::Layer::IpHeader;
799                                         err
800                                     } else {
801                                         err.clone()
802                                     }
803                                 })
804                             },
805                         );
806                     }
807                 }
808 
809                 // content error ipv6
810                 {
811                     use err::ip::HeaderError::*;
812                     let mut data = test.to_vec(&[]);
813 
814                     // inject an invalid ip version
815                     let base_len = data.len() - ipv6.header_len();
816                     data[base_len] = data[base_len] & 0b0000_1111;
817 
818                     from_slice_assert_err(
819                         &test,
820                         &data,
821                         if test.link.is_some() || test.vlan.is_some() {
822                             SliceError::Ipv6(err::ipv6::HeaderError::UnexpectedVersion {
823                                 version_number: 0,
824                             })
825                         } else {
826                             SliceError::Ip(UnsupportedIpVersion { version_number: 0 })
827                         },
828                     );
829                 }
830             }
831 
832             // ipv6 + extension
833             for fragment in [false, true] {
834                 let auth = IpAuthHeader::new(ip_number::GGP, 1, 2, &[]).unwrap();
835                 let frag = Ipv6FragmentHeader {
836                     next_header: ip_number::AUTH,
837                     fragment_offset: 0.try_into().unwrap(),
838                     more_fragments: fragment,
839                     identification: 3,
840                 };
841 
842                 let mut test = base.clone();
843                 test.set_ether_type(ether_type::IPV6);
844                 test.net = Some(NetHeaders::Ipv6(
845                     {
846                         let mut ipv6 = ipv6.clone();
847                         ipv6.next_header = ip_number::IPV6_FRAG;
848                         ipv6
849                     },
850                     {
851                         let mut exts: Ipv6Extensions = Default::default();
852                         exts.fragment = Some(frag.clone());
853                         exts.auth = Some(auth.clone());
854                         exts
855                     },
856                 ));
857                 test.set_payload_len(0);
858 
859                 // ok ipv6 & extensions
860                 from_x_slice_transport_variants(&test);
861 
862                 // ipv6 extension len error
863                 for len in 0..auth.header_len() {
864                     // set payload length
865                     let mut test = test.clone();
866                     test.set_payload_le_from_ip_on(
867                         -1 * (auth.header_len() as isize) + (len as isize),
868                     );
869 
870                     let data = test.to_vec(&[]);
871                     let base_len = test.len(&[]) - auth.header_len();
872 
873                     let err = LenError {
874                         required_len: auth.header_len(),
875                         len,
876                         len_source: LenSource::Ipv6HeaderPayloadLen,
877                         layer: err::Layer::IpAuthHeader,
878                         layer_start_offset: base_len,
879                     };
880                     from_slice_assert_err(
881                         &test,
882                         &data[..base_len + len],
883                         SliceError::Len(err.clone()),
884                     );
885                 }
886 
887                 // ipv6 extension content error (auth)
888                 {
889                     let mut data = test.to_vec(&[]);
890                     let auth_offset = data.len() - auth.header_len();
891                     // set the icv len too smaller then allowed
892                     data[auth_offset + 1] = 0;
893 
894                     let err = err::ip_auth::HeaderError::ZeroPayloadLen;
895                     from_slice_assert_err(
896                         &test,
897                         &data,
898                         SliceError::Ipv6Exts(err::ipv6_exts::HeaderError::IpAuth(err.clone())),
899                     );
900                 }
901 
902                 // ipv6 extension content error (hop by hop not at start)
903                 {
904                     let mut data = test.to_vec(&[]);
905                     let auth_offset = data.len() - auth.header_len();
906 
907                     // set the next header to be a hop-by-hop header to trigger a "not at start error"
908                     data[auth_offset] = 0;
909 
910                     from_slice_assert_err(
911                         &test,
912                         &data,
913                         SliceError::Ipv6Exts(err::ipv6_exts::HeaderError::HopByHopNotAtStart),
914                     );
915                 }
916             }
917         }
918     }
919 
from_x_slice_transport_variants(base: &TestPacket)920     fn from_x_slice_transport_variants(base: &TestPacket) {
921         // none
922         from_x_slice_assert_ok(base);
923 
924         // transport can only be set if ip is present
925         if let Some(ip) = &base.net {
926             // udp
927             {
928                 let udp = UdpHeader {
929                     source_port: 1,
930                     destination_port: 2,
931                     length: 3,
932                     checksum: 4,
933                 };
934                 let mut test = base.clone();
935                 test.net = Some({
936                     let mut ip = match ip {
937                         NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
938                         NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
939                     };
940                     ip.set_next_headers(ip_number::UDP);
941                     ip.into()
942                 });
943                 test.transport = Some(TransportHeader::Udp(udp.clone()));
944                 test.set_payload_len(0);
945 
946                 // ok decode
947                 from_x_slice_assert_ok(&test);
948 
949                 // length error
950                 if false == test.is_ip_payload_fragmented() {
951                     for len in 0..udp.header_len() {
952                         // build new test packet
953                         let mut test = test.clone();
954 
955                         // set payload length
956                         test.set_payload_le_from_ip_on(len as isize);
957 
958                         // generate data
959                         let data = test.to_vec(&[]);
960                         let base_len = test.len(&[]) - udp.header_len();
961 
962                         let err = LenError {
963                             required_len: udp.header_len(),
964                             len,
965                             len_source: match test.net.as_ref().unwrap() {
966                                 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
967                                 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
968                             },
969                             layer: err::Layer::UdpHeader,
970                             layer_start_offset: base_len,
971                         };
972                         from_slice_assert_err(
973                             &test,
974                             &data[..base_len + len],
975                             SliceError::Len(err.clone()),
976                         );
977                     }
978                 }
979             }
980 
981             // tcp
982             {
983                 let tcp = TcpHeader::new(1, 2, 3, 4);
984                 let mut test = base.clone();
985                 test.net = Some({
986                     let mut ip = match ip {
987                         NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
988                         NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
989                     };
990                     ip.set_next_headers(ip_number::TCP);
991                     ip.into()
992                 });
993                 test.transport = Some(TransportHeader::Tcp(tcp.clone()));
994                 test.set_payload_len(0);
995 
996                 // ok decode
997                 from_x_slice_assert_ok(&test);
998 
999                 // error can only occur if ip does not fragment the packet
1000                 if false == test.is_ip_payload_fragmented() {
1001                     // length error
1002                     for len in 0..(tcp.header_len() as usize) {
1003                         // set payload length
1004                         let mut test = test.clone();
1005                         test.set_payload_le_from_ip_on(len as isize);
1006 
1007                         let data = test.to_vec(&[]);
1008                         let base_len = test.len(&[]) - (tcp.header_len() as usize);
1009 
1010                         let err = LenError {
1011                             required_len: tcp.header_len() as usize,
1012                             len,
1013                             len_source: match test.net.as_ref().unwrap() {
1014                                 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1015                                 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1016                             },
1017                             layer: err::Layer::TcpHeader,
1018                             layer_start_offset: base_len,
1019                         };
1020                         from_slice_assert_err(
1021                             &test,
1022                             &data[..base_len + len],
1023                             SliceError::Len(err.clone()),
1024                         );
1025                     }
1026 
1027                     // content error
1028                     {
1029                         let mut data = test.to_vec(&[]);
1030                         let base_len = test.len(&[]) - (tcp.header_len() as usize);
1031 
1032                         // set data offset to 0 to trigger an error
1033                         data[base_len + 12] = data[base_len + 12] & 0b0000_1111;
1034 
1035                         let err = err::tcp::HeaderError::DataOffsetTooSmall { data_offset: 0 };
1036                         from_slice_assert_err(&test, &data, SliceError::Tcp(err.clone()));
1037                     }
1038                 }
1039             }
1040 
1041             // icmpv4
1042             {
1043                 let icmpv4 =
1044                     Icmpv4Header::new(Icmpv4Type::EchoReply(IcmpEchoHeader { id: 1, seq: 2 }));
1045                 let mut test = base.clone();
1046                 test.net = Some({
1047                     let mut ip = match ip {
1048                         NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1049                         NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1050                     };
1051                     ip.set_next_headers(ip_number::ICMP);
1052                     ip.into()
1053                 });
1054                 test.transport = Some(TransportHeader::Icmpv4(icmpv4.clone()));
1055 
1056                 // ok decode
1057                 from_x_slice_assert_ok(&test);
1058 
1059                 // length error
1060                 if false == test.is_ip_payload_fragmented() {
1061                     for len in 0..icmpv4.header_len() {
1062                         // set payload length
1063                         let mut test = test.clone();
1064                         test.set_payload_le_from_ip_on(len as isize);
1065 
1066                         let data = test.to_vec(&[]);
1067                         let base_len = test.len(&[]) - icmpv4.header_len();
1068 
1069                         let err = LenError {
1070                             required_len: icmpv4.header_len(),
1071                             len,
1072                             len_source: match test.net.as_ref().unwrap() {
1073                                 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1074                                 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1075                             },
1076                             layer: err::Layer::Icmpv4,
1077                             layer_start_offset: base_len,
1078                         };
1079                         from_slice_assert_err(
1080                             &test,
1081                             &data[..base_len + len],
1082                             SliceError::Len(err.clone()),
1083                         );
1084                     }
1085                 }
1086             }
1087 
1088             // icmpv6
1089             {
1090                 let icmpv6 =
1091                     Icmpv6Header::new(Icmpv6Type::EchoReply(IcmpEchoHeader { id: 1, seq: 2 }));
1092                 let mut test = base.clone();
1093                 test.net = Some({
1094                     let mut ip = match ip {
1095                         NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1096                         NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1097                     };
1098                     ip.set_next_headers(ip_number::IPV6_ICMP);
1099                     ip.into()
1100                 });
1101                 test.transport = Some(TransportHeader::Icmpv6(icmpv6.clone()));
1102 
1103                 // ok decode
1104                 from_x_slice_assert_ok(&test);
1105 
1106                 // length error
1107                 if false == test.is_ip_payload_fragmented() {
1108                     for len in 0..icmpv6.header_len() {
1109                         // set payload length
1110                         let mut test = test.clone();
1111                         test.set_payload_le_from_ip_on(len as isize);
1112 
1113                         let data = test.to_vec(&[]);
1114                         let base_len = test.len(&[]) - icmpv6.header_len();
1115 
1116                         let err = LenError {
1117                             required_len: icmpv6.header_len(),
1118                             len,
1119                             len_source: match test.net.as_ref().unwrap() {
1120                                 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1121                                 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1122                             },
1123                             layer: err::Layer::Icmpv6,
1124                             layer_start_offset: base_len,
1125                         };
1126                         from_slice_assert_err(
1127                             &test,
1128                             &data[..base_len + len],
1129                             SliceError::Len(err.clone()),
1130                         );
1131                     }
1132                 }
1133             }
1134         }
1135     }
1136 
from_x_slice_assert_ok(test_base: &TestPacket)1137     fn from_x_slice_assert_ok(test_base: &TestPacket) {
1138         let payload = [1, 2, 3, 4];
1139 
1140         // set length fields in ip headers
1141         let test = {
1142             let mut test = test_base.clone();
1143             test.set_payload_len(payload.len());
1144             test
1145         };
1146 
1147         // check if fragmenting
1148         let is_fragmented = test.is_ip_payload_fragmented();
1149 
1150         // write data
1151         let data = test.to_vec(&payload);
1152 
1153         // from_ethernet_slice
1154         if test.link.is_some() {
1155             let result = PacketHeaders::from_ethernet_slice(&data).unwrap();
1156             assert_eq!(result.link, test.link);
1157             assert_eq!(result.vlan, test.vlan);
1158             assert_eq!(result.net, test.net);
1159             if is_fragmented {
1160                 assert_eq!(result.transport, None);
1161             } else {
1162                 assert_eq!(result.transport, test.transport);
1163                 assert_eq!(result.payload.slice(), &[1, 2, 3, 4]);
1164             }
1165         }
1166         // from_ether_type (vlan at start)
1167         if test.link.is_none() && test.vlan.is_some() {
1168             for ether_type in VLAN_ETHER_TYPES {
1169                 let result = PacketHeaders::from_ether_type(ether_type, &data).unwrap();
1170                 assert_eq!(result.link, test.link);
1171                 assert_eq!(result.vlan, test.vlan);
1172                 assert_eq!(result.net, test.net);
1173                 if is_fragmented {
1174                     assert_eq!(result.transport, None);
1175                 } else {
1176                     assert_eq!(result.transport, test.transport);
1177                     assert_eq!(result.payload.slice(), &[1, 2, 3, 4]);
1178                 }
1179             }
1180         }
1181         // from_ether_type (ip at start)
1182         if test.link.is_none() && test.vlan.is_none() {
1183             if let Some(ip) = &test.net {
1184                 let result = PacketHeaders::from_ether_type(
1185                     match ip {
1186                         NetHeaders::Ipv4(_, _) => ether_type::IPV4,
1187                         NetHeaders::Ipv6(_, _) => ether_type::IPV6,
1188                     },
1189                     &data,
1190                 )
1191                 .unwrap();
1192                 assert_eq!(result.link, test.link);
1193                 assert_eq!(result.vlan, test.vlan);
1194                 assert_eq!(result.net, test.net);
1195                 if is_fragmented {
1196                     assert_eq!(result.transport, None);
1197                 } else {
1198                     assert_eq!(result.transport, test.transport);
1199                     assert_eq!(result.payload.slice(), &[1, 2, 3, 4]);
1200                 }
1201             }
1202         }
1203         // from_ip_slice
1204         if test.link.is_none() && test.vlan.is_none() && test.net.is_some() {
1205             let result = PacketHeaders::from_ip_slice(&data).unwrap();
1206             assert_eq!(result.link, test.link);
1207             assert_eq!(result.vlan, test.vlan);
1208             assert_eq!(result.net, test.net);
1209             if is_fragmented {
1210                 assert_eq!(result.transport, None);
1211             } else {
1212                 assert_eq!(result.transport, test.transport);
1213                 assert_eq!(result.payload.slice(), &[1, 2, 3, 4]);
1214             }
1215         }
1216     }
1217 
1218     /// Check that the given errors get triggered if presented with the given
1219     /// data.
from_slice_assert_err(test: &TestPacket, data: &[u8], err: SliceError)1220     fn from_slice_assert_err(test: &TestPacket, data: &[u8], err: SliceError) {
1221         // from_ethernet_slice
1222         if test.link.is_some() {
1223             assert_eq!(
1224                 err.clone(),
1225                 PacketHeaders::from_ethernet_slice(&data).unwrap_err()
1226             );
1227         }
1228         // from_ether_type (vlan at start)
1229         if test.link.is_none() && test.vlan.is_some() {
1230             for ether_type in VLAN_ETHER_TYPES {
1231                 assert_eq!(
1232                     err.clone(),
1233                     PacketHeaders::from_ether_type(ether_type, &data).unwrap_err()
1234                 );
1235             }
1236         }
1237         // from_ether_type (ip at start)
1238         if test.link.is_none() && test.vlan.is_none() {
1239             if let Some(ip) = &test.net {
1240                 let err = PacketHeaders::from_ether_type(
1241                     match ip {
1242                         NetHeaders::Ipv4(_, _) => ether_type::IPV4,
1243                         NetHeaders::Ipv6(_, _) => ether_type::IPV6,
1244                     },
1245                     &data,
1246                 )
1247                 .unwrap_err();
1248                 assert_eq!(err, err.clone());
1249             }
1250         }
1251         // from_ip_slice
1252         if test.link.is_none() && test.vlan.is_none() && test.net.is_some() {
1253             assert_eq!(err, PacketHeaders::from_ip_slice(&data).unwrap_err());
1254         }
1255     }
1256 }
1257