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