zero_packet/packet/
builder.rs

1use crate::{
2    datalink::{
3        arp::ArpWriter,
4        ethernet::{
5            EthernetWriter, ETHERNET_MIN_HEADER_LENGTH, ETHERTYPE_QINQ, ETHERTYPE_VLAN,
6            VLAN_TAG_LENGTH,
7        },
8    },
9    network::{
10        checksum::pseudo_header,
11        extensions::{
12            authentication::AuthenticationHeaderWriter, fragment::FragmentHeaderWriter,
13            options::OptionsHeaderWriter, routing::RoutingHeaderWriter,
14        },
15        icmpv4::Icmpv4Writer,
16        icmpv6::Icmpv6Writer,
17        ipv4::IPv4Writer,
18        ipv6::IPv6Writer,
19    },
20    transport::{tcp::TcpWriter, udp::UdpWriter},
21};
22
23// Note:
24// Implementing a builder pattern for packet construction using the typestate pattern.
25// The typestate pattern encodes state transitions in the type system at compile-time.
26// This pattern is used to ensure that the packet is built structurally correct.
27
28// State machine states. Zero-sized structs (ZSTs).
29pub struct RawState;
30pub struct EthernetHeaderState;
31pub struct ArpHeaderState;
32pub struct Ipv4HeaderState;
33pub struct Ipv6HeaderState;
34pub struct TcpHeaderState;
35pub struct UdpHeaderState;
36pub struct Icmpv4HeaderState;
37pub struct Icmpv6HeaderState;
38pub struct Ipv4EncapsulatedState;
39pub struct Ipv6EncapsulatedState;
40pub struct HopByHopOptionsState;
41pub struct DestinationOptions1State;
42pub struct DestinationOptions2State;
43pub struct RoutingHeaderState;
44pub struct FragmentHeaderState;
45pub struct AuthHeaderState;
46
47/// A zero-copy packet builder.
48///
49/// Using the typestate pattern, a state machine is implemented using the type system.
50/// The state machine ensures that the package is built correctly.
51///
52/// The creation of new `PacketBuilder` instances happens on the stack.
53/// These stack allocations are very cheap and most likely optimized away by the compiler.
54/// The state types are zero-sized types (ZSTs) and don't consume any memory.
55pub struct PacketBuilder<'a, State> {
56    bytes: &'a mut [u8],
57    header_len: usize,
58    _state: State,
59}
60
61// All states share these methods.
62impl<'a, State> PacketBuilder<'a, State> {
63    /// Returns the length of all encapsulated headers in bytes.
64    #[inline]
65    pub fn header_len(&self) -> usize {
66        self.header_len
67    }
68
69    /// Returns the length of the payload in bytes.
70    ///
71    /// Payload is the data after all headers.
72    #[inline]
73    pub fn payload_len(&self) -> usize {
74        self.bytes.len() - self.header_len
75    }
76
77    /// Returns a reference to the payload.
78    ///
79    /// Payload is the data after all headers.
80    #[inline]
81    pub fn payload(&self) -> &[u8] {
82        &self.bytes[self.header_len..]
83    }
84
85    /// Returns a reference to the data slice.
86    #[inline]
87    pub fn build(self) -> &'a [u8] {
88        self.bytes
89    }
90}
91
92// Usage of macros to reduce code duplication.
93
94macro_rules! impl_raw {
95    ($state:ty) => {
96        impl<'a> PacketBuilder<'a, $state> {
97            #[inline]
98            pub fn new(bytes: &'a mut [u8]) -> PacketBuilder<'a, RawState> {
99                PacketBuilder {
100                    bytes,
101                    header_len: 0,
102                    _state: RawState,
103                }
104            }
105        }
106    };
107}
108
109macro_rules! impl_ethernet {
110    ($state:ty) => {
111        impl<'a> PacketBuilder<'a, $state> {
112            #[inline]
113            pub fn ethernet(
114                mut self,
115                src_mac: &[u8; 6],
116                dest_mac: &[u8; 6],
117                ethertype: u16,
118            ) -> Result<PacketBuilder<'a, EthernetHeaderState>, &'static str> {
119                let mut writer = EthernetWriter::new(self.bytes)?;
120
121                writer.set_src_mac(src_mac);
122                writer.set_dest_mac(dest_mac);
123                writer.set_ethertype(ethertype);
124
125                self.header_len = ETHERNET_MIN_HEADER_LENGTH;
126
127                Ok(PacketBuilder {
128                    bytes: self.bytes,
129                    header_len: self.header_len,
130                    _state: EthernetHeaderState,
131                })
132            }
133        }
134    };
135}
136
137macro_rules! impl_ethernet_vlan {
138    ($state:ty) => {
139        impl<'a> PacketBuilder<'a, $state> {
140            #[inline]
141            pub fn ethernet_vlan(
142                mut self,
143                src_mac: &[u8; 6],
144                dest_mac: &[u8; 6],
145                ethertype: u16,
146                tci: u16,
147            ) -> Result<PacketBuilder<'a, EthernetHeaderState>, &'static str> {
148                let mut writer = EthernetWriter::new(self.bytes)?;
149
150                writer.set_src_mac(src_mac);
151                writer.set_dest_mac(dest_mac);
152                writer.set_vlan_tag(ETHERTYPE_VLAN, tci)?;
153                writer.set_ethertype(ethertype);
154
155                self.header_len = ETHERNET_MIN_HEADER_LENGTH + VLAN_TAG_LENGTH;
156
157                Ok(PacketBuilder {
158                    bytes: self.bytes,
159                    header_len: self.header_len,
160                    _state: EthernetHeaderState,
161                })
162            }
163        }
164    };
165}
166
167macro_rules! impl_ethernet_qinq {
168    ($state:ty) => {
169        impl<'a> PacketBuilder<'a, $state> {
170            #[inline]
171            pub fn ethernet_qinq(
172                mut self,
173                src_mac: &[u8; 6],
174                dest_mac: &[u8; 6],
175                ethertype: u16,
176                tci1: u16,
177                tci2: u16,
178            ) -> Result<PacketBuilder<'a, EthernetHeaderState>, &'static str> {
179                let mut writer = EthernetWriter::new(self.bytes)?;
180
181                writer.set_src_mac(src_mac);
182                writer.set_dest_mac(dest_mac);
183                writer.set_double_vlan_tag(ETHERTYPE_QINQ, tci1, ETHERTYPE_VLAN, tci2)?;
184                writer.set_ethertype(ethertype);
185
186                self.header_len = ETHERNET_MIN_HEADER_LENGTH + 2 * VLAN_TAG_LENGTH;
187
188                Ok(PacketBuilder {
189                    bytes: self.bytes,
190                    header_len: self.header_len,
191                    _state: EthernetHeaderState,
192                })
193            }
194        }
195    };
196}
197
198macro_rules! impl_arp {
199    ($state:ty) => {
200        impl<'a> PacketBuilder<'a, $state> {
201            #[inline]
202            #[allow(clippy::too_many_arguments)]
203            pub fn arp(
204                mut self,
205                hardware_type: u16,
206                protocol_type: u16,
207                hardware_address_length: u8,
208                protocol_address_length: u8,
209                operation: u16,
210                src_mac: &[u8; 6],
211                src_ip: &[u8; 4],
212                dest_mac: &[u8; 6],
213                dest_ip: &[u8; 4],
214            ) -> Result<PacketBuilder<'a, ArpHeaderState>, &'static str> {
215                if self.bytes.len() < self.header_len {
216                    return Err("Data too short to contain an ARP header.");
217                }
218
219                let mut writer = ArpWriter::new(&mut self.bytes[self.header_len..])?;
220
221                writer.set_htype(hardware_type);
222                writer.set_ptype(protocol_type);
223                writer.set_hlen(hardware_address_length);
224                writer.set_plen(protocol_address_length);
225                writer.set_oper(operation);
226                writer.set_sha(src_mac);
227                writer.set_spa(src_ip);
228                writer.set_tha(dest_mac);
229                writer.set_tpa(dest_ip);
230
231                self.header_len += writer.header_len();
232
233                Ok(PacketBuilder {
234                    bytes: self.bytes,
235                    header_len: self.header_len,
236                    _state: ArpHeaderState,
237                })
238            }
239        }
240    };
241}
242
243macro_rules! impl_ipv4 {
244    ($state:ty) => {
245        impl<'a> PacketBuilder<'a, $state> {
246            #[inline]
247            #[allow(clippy::too_many_arguments)]
248            pub fn ipv4(
249                mut self,
250                version: u8,
251                ihl: u8,
252                dscp: u8,
253                ecn: u8,
254                total_length: u16,
255                identification: u16,
256                flags: u8,
257                fragment_offset: u16,
258                ttl: u8,
259                protocol: u8,
260                src_ip: &[u8; 4],
261                dest_ip: &[u8; 4],
262            ) -> Result<PacketBuilder<'a, Ipv4HeaderState>, &'static str> {
263                if self.bytes.len() < self.header_len {
264                    return Err("Data too short to contain an IPv4 header.");
265                }
266
267                let mut writer = IPv4Writer::new(&mut self.bytes[self.header_len..])?;
268
269                writer.set_version(version);
270                writer.set_ihl(ihl);
271                writer.set_dscp(dscp);
272                writer.set_ecn(ecn);
273                writer.set_total_length(total_length);
274                writer.set_id(identification);
275                writer.set_flags(flags);
276                writer.set_fragment_offset(fragment_offset);
277                writer.set_ttl(ttl);
278                writer.set_protocol(protocol);
279                writer.set_src_ip(src_ip);
280                writer.set_dest_ip(dest_ip);
281                writer.set_checksum();
282
283                self.header_len += writer.header_len();
284
285                Ok(PacketBuilder {
286                    bytes: self.bytes,
287                    header_len: self.header_len,
288                    _state: Ipv4HeaderState,
289                })
290            }
291        }
292    };
293}
294
295macro_rules! impl_ipv6 {
296    ($state:ty) => {
297        impl<'a> PacketBuilder<'a, $state> {
298            #[inline]
299            #[allow(clippy::too_many_arguments)]
300            pub fn ipv6(
301                mut self,
302                version: u8,
303                traffic_class: u8,
304                flow_label: u32,
305                payload_length: u16,
306                next_header: u8,
307                hop_limit: u8,
308                src_addr: &[u8; 16],
309                dest_addr: &[u8; 16],
310            ) -> Result<PacketBuilder<'a, Ipv6HeaderState>, &'static str> {
311                if self.bytes.len() < self.header_len {
312                    return Err("Data too short to contain an IPv6 header.");
313                }
314
315                let mut writer = IPv6Writer::new(&mut self.bytes[self.header_len..])?;
316
317                writer.set_version(version);
318                writer.set_traffic_class(traffic_class);
319                writer.set_flow_label(flow_label);
320                writer.set_payload_length(payload_length);
321                writer.set_next_header(next_header);
322                writer.set_hop_limit(hop_limit);
323                writer.set_src_addr(src_addr);
324                writer.set_dest_addr(dest_addr);
325
326                self.header_len += writer.header_len();
327
328                Ok(PacketBuilder {
329                    bytes: self.bytes,
330                    header_len: self.header_len,
331                    _state: Ipv6HeaderState,
332                })
333            }
334        }
335    };
336}
337
338macro_rules! impl_ipv4_encapsulated {
339    ($state:ty) => {
340        impl<'a> PacketBuilder<'a, $state> {
341            #[inline]
342            #[allow(clippy::too_many_arguments)]
343            pub fn ipv4(
344                mut self,
345                version: u8,
346                ihl: u8,
347                dscp: u8,
348                ecn: u8,
349                total_length: u16,
350                identification: u16,
351                flags: u8,
352                fragment_offset: u16,
353                ttl: u8,
354                protocol: u8,
355                src_ip: &[u8; 4],
356                dest_ip: &[u8; 4],
357            ) -> Result<PacketBuilder<'a, Ipv4EncapsulatedState>, &'static str> {
358                if self.bytes.len() < self.header_len {
359                    return Err("Data too short to contain an IPv4 header.");
360                }
361
362                let mut writer = IPv4Writer::new(&mut self.bytes[self.header_len..])?;
363
364                writer.set_version(version);
365                writer.set_ihl(ihl);
366                writer.set_dscp(dscp);
367                writer.set_ecn(ecn);
368                writer.set_total_length(total_length);
369                writer.set_id(identification);
370                writer.set_flags(flags);
371                writer.set_fragment_offset(fragment_offset);
372                writer.set_ttl(ttl);
373                writer.set_protocol(protocol);
374                writer.set_src_ip(src_ip);
375                writer.set_dest_ip(dest_ip);
376                writer.set_checksum();
377
378                self.header_len += writer.header_len();
379
380                Ok(PacketBuilder {
381                    bytes: self.bytes,
382                    header_len: self.header_len,
383                    _state: Ipv4EncapsulatedState,
384                })
385            }
386        }
387    };
388}
389
390macro_rules! impl_ipv6_encapsulated {
391    ($state:ty) => {
392        impl<'a> PacketBuilder<'a, $state> {
393            #[inline]
394            #[allow(clippy::too_many_arguments)]
395            pub fn ipv6(
396                mut self,
397                version: u8,
398                traffic_class: u8,
399                flow_label: u32,
400                payload_length: u16,
401                next_header: u8,
402                hop_limit: u8,
403                src_addr: &[u8; 16],
404                dest_addr: &[u8; 16],
405            ) -> Result<PacketBuilder<'a, Ipv6EncapsulatedState>, &'static str> {
406                if self.bytes.len() < self.header_len {
407                    return Err("Data too short to contain an IPv6 header.");
408                }
409
410                let mut writer = IPv6Writer::new(&mut self.bytes[self.header_len..])?;
411
412                writer.set_version(version);
413                writer.set_traffic_class(traffic_class);
414                writer.set_flow_label(flow_label);
415                writer.set_payload_length(payload_length);
416                writer.set_next_header(next_header);
417                writer.set_hop_limit(hop_limit);
418                writer.set_src_addr(src_addr);
419                writer.set_dest_addr(dest_addr);
420
421                self.header_len += writer.header_len();
422
423                Ok(PacketBuilder {
424                    bytes: self.bytes,
425                    header_len: self.header_len,
426                    _state: Ipv6EncapsulatedState,
427                })
428            }
429        }
430    };
431}
432
433macro_rules! impl_tcp {
434    ($state:ty, $addr_type:ty) => {
435        impl<'a> PacketBuilder<'a, $state> {
436            #[allow(clippy::too_many_arguments)]
437            #[inline]
438            pub fn tcp(
439                mut self,
440                src_ip: $addr_type,
441                src_port: u16,
442                dest_ip: $addr_type,
443                dest_port: u16,
444                sequence_number: u32,
445                acknowledgment_number: u32,
446                data_offset: u8,
447                reserved: u8,
448                flags: u8,
449                window_size: u16,
450                urgent_pointer: u16,
451                payload: Option<&[u8]>,
452            ) -> Result<PacketBuilder<'a, TcpHeaderState>, &'static str> {
453                if self.bytes.len() < self.header_len {
454                    return Err("Data too short to contain a TCP segment.");
455                }
456
457                let mut writer = TcpWriter::new(&mut self.bytes[self.header_len..])?;
458
459                writer.set_src_port(src_port);
460                writer.set_dest_port(dest_port);
461                writer.set_sequence_number(sequence_number);
462                writer.set_ack_number(acknowledgment_number);
463                writer.set_data_offset(data_offset);
464                writer.set_reserved(reserved);
465                writer.set_flags(flags);
466                writer.set_window_size(window_size);
467                writer.set_urgent_pointer(urgent_pointer);
468
469                if let Some(payload) = payload {
470                    writer.set_payload(payload)?;
471                }
472
473                let pseudo_sum = pseudo_header(src_ip, dest_ip, 6, writer.packet_len());
474                writer.set_checksum(pseudo_sum);
475
476                self.header_len += writer.header_len();
477
478                Ok(PacketBuilder {
479                    bytes: self.bytes,
480                    header_len: self.header_len,
481                    _state: TcpHeaderState,
482                })
483            }
484        }
485    };
486}
487
488macro_rules! impl_udp {
489    ($state:ty, $addr_type:ty) => {
490        impl<'a> PacketBuilder<'a, $state> {
491            #[inline]
492            pub fn udp(
493                mut self,
494                src_addr: $addr_type,
495                src_port: u16,
496                dest_addr: $addr_type,
497                dest_port: u16,
498                length: u16,
499                payload: Option<&[u8]>,
500            ) -> Result<PacketBuilder<'a, UdpHeaderState>, &'static str> {
501                if self.bytes.len() < self.header_len {
502                    return Err("Data too short to contain a UDP datagram.");
503                }
504
505                let mut writer = UdpWriter::new(&mut self.bytes[self.header_len..])?;
506
507                writer.set_src_port(src_port);
508                writer.set_dest_port(dest_port);
509                writer.set_length(length);
510
511                if let Some(payload) = payload {
512                    writer.set_payload(payload)?;
513                }
514
515                let pseudo_sum = pseudo_header(src_addr, dest_addr, 17, writer.packet_len());
516                writer.set_checksum(pseudo_sum);
517
518                self.header_len += writer.header_len();
519
520                Ok(PacketBuilder {
521                    bytes: self.bytes,
522                    header_len: self.header_len,
523                    _state: UdpHeaderState,
524                })
525            }
526        }
527    };
528}
529
530macro_rules! impl_icmpv4 {
531    ($state:ty) => {
532        impl<'a> PacketBuilder<'a, $state> {
533            #[inline]
534            pub fn icmpv4(
535                mut self,
536                icmp_type: u8,
537                icmp_code: u8,
538                payload: Option<&[u8]>,
539            ) -> Result<PacketBuilder<'a, Icmpv4HeaderState>, &'static str> {
540                if self.bytes.len() < self.header_len {
541                    return Err("Data too short to contain an ICMP packet.");
542                }
543
544                let mut writer = Icmpv4Writer::new(&mut self.bytes[self.header_len..])?;
545
546                writer.set_icmp_type(icmp_type);
547                writer.set_icmp_code(icmp_code);
548
549                if let Some(payload) = payload {
550                    writer.set_payload(payload)?;
551                }
552
553                writer.set_checksum();
554
555                self.header_len += writer.header_len();
556
557                Ok(PacketBuilder {
558                    bytes: self.bytes,
559                    header_len: self.header_len,
560                    _state: Icmpv4HeaderState,
561                })
562            }
563        }
564    };
565}
566
567macro_rules! impl_icmpv6 {
568    ($state:ty, $addr_type:ty) => {
569        impl<'a> PacketBuilder<'a, $state> {
570            #[inline]
571            pub fn icmpv6(
572                mut self,
573                src_addr: $addr_type,
574                dest_addr: $addr_type,
575                icmp_type: u8,
576                icmp_code: u8,
577                payload: Option<&[u8]>,
578            ) -> Result<PacketBuilder<'a, Icmpv6HeaderState>, &'static str> {
579                if self.bytes.len() < self.header_len {
580                    return Err("Data too short to contain an ICMPv6 packet.");
581                }
582
583                let mut writer = Icmpv6Writer::new(&mut self.bytes[self.header_len..])?;
584
585                writer.set_icmp_type(icmp_type);
586                writer.set_icmp_code(icmp_code);
587
588                if let Some(payload) = payload {
589                    writer.set_payload(payload)?;
590                }
591
592                let pseudo_sum = pseudo_header(src_addr, dest_addr, 58, writer.packet_len());
593                writer.set_checksum(pseudo_sum);
594
595                self.header_len += writer.header_len();
596
597                Ok(PacketBuilder {
598                    bytes: self.bytes,
599                    header_len: self.header_len,
600                    _state: Icmpv6HeaderState,
601                })
602            }
603        }
604    };
605}
606
607macro_rules! impl_hop_by_hop {
608    ($state:ty) => {
609        impl<'a> PacketBuilder<'a, $state> {
610            #[inline]
611            pub fn hop_by_hop(
612                mut self,
613                next_header: u8,
614                extension_len: u8,
615                options: &[u8],
616            ) -> Result<PacketBuilder<'a, HopByHopOptionsState>, &'static str> {
617                if self.bytes.len() < self.header_len {
618                    return Err("Data too short to contain an IPv6 Hop-by-Hop Options header.");
619                }
620
621                let mut writer = OptionsHeaderWriter::new(&mut self.bytes[self.header_len..])?;
622
623                writer.set_next_header(next_header);
624                writer.set_header_ext_len(extension_len);
625                writer.set_options(options)?;
626
627                self.header_len += writer.header_len();
628
629                Ok(PacketBuilder {
630                    bytes: self.bytes,
631                    header_len: self.header_len,
632                    _state: HopByHopOptionsState,
633                })
634            }
635        }
636    };
637}
638
639macro_rules! impl_destination_options_1 {
640    ($state:ty) => {
641        impl<'a> PacketBuilder<'a, $state> {
642            #[inline]
643            pub fn destination_options1(
644                mut self,
645                next_header: u8,
646                extension_len: u8,
647                options: &[u8],
648            ) -> Result<PacketBuilder<'a, DestinationOptions1State>, &'static str> {
649                if self.bytes.len() < self.header_len {
650                    return Err("Data too short to contain an IPv6 Destination Options header.");
651                }
652
653                let mut writer = OptionsHeaderWriter::new(&mut self.bytes[self.header_len..])?;
654
655                writer.set_next_header(next_header);
656                writer.set_header_ext_len(extension_len);
657                writer.set_options(options)?;
658
659                self.header_len += writer.header_len();
660
661                Ok(PacketBuilder {
662                    bytes: self.bytes,
663                    header_len: self.header_len,
664                    _state: DestinationOptions1State,
665                })
666            }
667        }
668    };
669}
670
671macro_rules! impl_routing_header {
672    ($state:ty) => {
673        impl<'a> PacketBuilder<'a, $state> {
674            #[inline]
675            pub fn routing_header(
676                mut self,
677                next_header: u8,
678                header_ext_len: u8,
679                routing_type: u8,
680                segments_left: u8,
681                data: &[u8],
682            ) -> Result<PacketBuilder<'a, RoutingHeaderState>, &'static str> {
683                if self.bytes.len() < self.header_len {
684                    return Err("Data too short to contain an IPv6 Routing header.");
685                }
686
687                let mut writer = RoutingHeaderWriter::new(&mut self.bytes[self.header_len..])?;
688
689                writer.set_next_header(next_header);
690                writer.set_header_ext_len(header_ext_len);
691                writer.set_routing_type(routing_type);
692                writer.set_segments_left(segments_left);
693                writer.set_data(data)?;
694
695                self.header_len += writer.header_len();
696
697                Ok(PacketBuilder {
698                    bytes: self.bytes,
699                    header_len: self.header_len,
700                    _state: RoutingHeaderState,
701                })
702            }
703        }
704    };
705}
706
707macro_rules! impl_fragment_header {
708    ($state:ty) => {
709        impl<'a> PacketBuilder<'a, $state> {
710            #[inline]
711            pub fn fragment_header(
712                mut self,
713                next_header: u8,
714                fragment_offset: u16,
715                m_flag: bool,
716                identification: u32,
717            ) -> Result<PacketBuilder<'a, FragmentHeaderState>, &'static str> {
718                if self.bytes.len() < self.header_len {
719                    return Err("Data too short to contain an IPv6 Routing header.");
720                }
721
722                let mut writer = FragmentHeaderWriter::new(&mut self.bytes[self.header_len..])?;
723
724                writer.set_next_header(next_header);
725                writer.set_reserved(0);
726                writer.set_fragment_offset(fragment_offset);
727                writer.set_res(0);
728                writer.set_m_flag(m_flag);
729                writer.set_identification(identification);
730
731                self.header_len += writer.header_len();
732
733                Ok(PacketBuilder {
734                    bytes: self.bytes,
735                    header_len: self.header_len,
736                    _state: FragmentHeaderState,
737                })
738            }
739        }
740    };
741}
742
743macro_rules! impl_authentication_header {
744    ($state:ty) => {
745        impl<'a> PacketBuilder<'a, $state> {
746            #[inline]
747            pub fn authentication_header(
748                mut self,
749                next_header: u8,
750                payload_len: u8,
751                spi: u32,
752                seq_num: u32,
753                auth_data: &[u8],
754            ) -> Result<PacketBuilder<'a, AuthHeaderState>, &'static str> {
755                if self.bytes.len() < self.header_len {
756                    return Err("Data too short to contain an IPv6 Authentication header.");
757                }
758
759                let mut writer =
760                    AuthenticationHeaderWriter::new(&mut self.bytes[self.header_len..])?;
761
762                writer.set_next_header(next_header);
763                writer.set_payload_len(payload_len);
764                writer.set_reserved(0);
765                writer.set_spi(spi);
766                writer.set_sequence_number(seq_num);
767                writer.set_authentication_data(auth_data)?;
768
769                self.header_len += writer.header_len();
770
771                Ok(PacketBuilder {
772                    bytes: self.bytes,
773                    header_len: self.header_len,
774                    _state: AuthHeaderState,
775                })
776            }
777        }
778    };
779}
780
781macro_rules! impl_destination_options_2 {
782    ($state:ty) => {
783        impl<'a> PacketBuilder<'a, $state> {
784            #[inline]
785            pub fn destination_options2(
786                mut self,
787                next_header: u8,
788                extension_len: u8,
789                options: &[u8],
790            ) -> Result<PacketBuilder<'a, DestinationOptions2State>, &'static str> {
791                if self.bytes.len() < self.header_len {
792                    return Err("Data too short to contain an IPv6 Destination Options header.");
793                }
794
795                let mut writer = OptionsHeaderWriter::new(&mut self.bytes[self.header_len..])?;
796
797                writer.set_next_header(next_header);
798                writer.set_header_ext_len(extension_len);
799                writer.set_options(options)?;
800
801                self.header_len += writer.header_len();
802
803                Ok(PacketBuilder {
804                    bytes: self.bytes,
805                    header_len: self.header_len,
806                    _state: DestinationOptions2State,
807                })
808            }
809        }
810    };
811}
812
813// Implementing the state machine transitions.
814// We adhere to the recommended extension header order according to RFC 2460.
815
816// Raw
817impl_raw!(RawState);
818impl_ethernet!(RawState);
819impl_ethernet_vlan!(RawState);
820impl_ethernet_qinq!(RawState);
821
822// EthernetHeader
823impl_arp!(EthernetHeaderState);
824impl_ipv4!(EthernetHeaderState);
825impl_ipv6!(EthernetHeaderState);
826
827// Ipv4Encapsulated
828impl_tcp!(Ipv4EncapsulatedState, &[u8; 4]);
829impl_udp!(Ipv4EncapsulatedState, &[u8; 4]);
830impl_icmpv4!(Ipv4EncapsulatedState);
831
832// Ipv6Encapsulated
833impl_tcp!(Ipv6EncapsulatedState, &[u8; 16]);
834impl_udp!(Ipv6EncapsulatedState, &[u8; 16]);
835impl_icmpv6!(Ipv6EncapsulatedState, &[u8; 16]);
836
837// IPv4Header
838impl_tcp!(Ipv4HeaderState, &[u8; 4]);
839impl_udp!(Ipv4HeaderState, &[u8; 4]);
840impl_icmpv4!(Ipv4HeaderState);
841impl_ipv4_encapsulated!(Ipv4HeaderState);
842impl_ipv6_encapsulated!(Ipv4HeaderState);
843
844// IPv6Header
845impl_tcp!(Ipv6HeaderState, &[u8; 16]);
846impl_udp!(Ipv6HeaderState, &[u8; 16]);
847impl_icmpv6!(Ipv6HeaderState, &[u8; 16]);
848impl_ipv4_encapsulated!(Ipv6HeaderState);
849impl_ipv6_encapsulated!(Ipv6HeaderState);
850impl_hop_by_hop!(Ipv6HeaderState);
851impl_destination_options_1!(Ipv6HeaderState);
852impl_routing_header!(Ipv6HeaderState);
853impl_fragment_header!(Ipv6HeaderState);
854impl_authentication_header!(Ipv6HeaderState);
855impl_destination_options_2!(Ipv6HeaderState);
856
857// HopByHopOptions
858impl_tcp!(HopByHopOptionsState, &[u8; 16]);
859impl_udp!(HopByHopOptionsState, &[u8; 16]);
860impl_icmpv6!(HopByHopOptionsState, &[u8; 16]);
861impl_ipv4_encapsulated!(HopByHopOptionsState);
862impl_ipv6_encapsulated!(HopByHopOptionsState);
863impl_destination_options_1!(HopByHopOptionsState);
864impl_routing_header!(HopByHopOptionsState);
865impl_fragment_header!(HopByHopOptionsState);
866impl_authentication_header!(HopByHopOptionsState);
867impl_destination_options_2!(HopByHopOptionsState);
868
869// DestinationOptions1
870impl_tcp!(DestinationOptions1State, &[u8; 16]);
871impl_udp!(DestinationOptions1State, &[u8; 16]);
872impl_icmpv6!(DestinationOptions1State, &[u8; 16]);
873impl_ipv4_encapsulated!(DestinationOptions1State);
874impl_ipv6_encapsulated!(DestinationOptions1State);
875impl_routing_header!(DestinationOptions1State);
876
877// RoutingHeader
878impl_tcp!(RoutingHeaderState, &[u8; 16]);
879impl_udp!(RoutingHeaderState, &[u8; 16]);
880impl_icmpv6!(RoutingHeaderState, &[u8; 16]);
881impl_ipv4_encapsulated!(RoutingHeaderState);
882impl_ipv6_encapsulated!(RoutingHeaderState);
883impl_fragment_header!(RoutingHeaderState);
884impl_authentication_header!(RoutingHeaderState);
885impl_destination_options_2!(RoutingHeaderState);
886
887// FragmentHeader
888impl_tcp!(FragmentHeaderState, &[u8; 16]);
889impl_udp!(FragmentHeaderState, &[u8; 16]);
890impl_icmpv6!(FragmentHeaderState, &[u8; 16]);
891impl_ipv4_encapsulated!(FragmentHeaderState);
892impl_ipv6_encapsulated!(FragmentHeaderState);
893impl_authentication_header!(FragmentHeaderState);
894impl_destination_options_2!(FragmentHeaderState);
895
896// AuthHeader
897impl_tcp!(AuthHeaderState, &[u8; 16]);
898impl_udp!(AuthHeaderState, &[u8; 16]);
899impl_icmpv6!(AuthHeaderState, &[u8; 16]);
900impl_ipv4_encapsulated!(AuthHeaderState);
901impl_ipv6_encapsulated!(AuthHeaderState);
902impl_destination_options_2!(AuthHeaderState);
903
904// DestinationOptions2
905impl_tcp!(DestinationOptions2State, &[u8; 16]);
906impl_udp!(DestinationOptions2State, &[u8; 16]);
907impl_icmpv6!(DestinationOptions2State, &[u8; 16]);
908impl_ipv4_encapsulated!(DestinationOptions2State);
909impl_ipv6_encapsulated!(DestinationOptions2State);
910
911#[cfg(test)]
912mod tests {
913    use super::*;
914    use crate::{
915        datalink::arp::ARP_HEADER_LENGTH, misc::IpInIp, network::ipv4::IPV4_MIN_HEADER_LENGTH,
916        packet::parser::PacketParser, transport::udp::UDP_HEADER_LENGTH,
917    };
918
919    #[test]
920    fn write_payload() {
921        // Raw packet data.
922        let mut buffer = [0u8; 64];
923
924        let payload = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
925
926        // Construct PacketBuilder with an Ethernet header, an IPv4 header, a UDP header, and a payload.
927        let packet_builder = PacketBuilder::new(&mut buffer)
928            // 14 bytes
929            .ethernet(&[1, 2, 3, 4, 5, 6], &[7, 8, 9, 10, 11, 12], 0x0800)
930            .unwrap()
931            // 20 bytes
932            .ipv4(
933                4,
934                5,
935                0,
936                0,
937                50,
938                0,
939                0,
940                0,
941                64,
942                17,
943                &[192, 168, 1, 1],
944                &[192, 168, 1, 2],
945            )
946            .unwrap()
947            // 8 bytes + 10 bytes
948            .udp(
949                &[192, 168, 1, 1],
950                12345,
951                &[192, 168, 1, 2],
952                54321,
953                30,
954                Some(&payload),
955            )
956            .unwrap();
957
958        // Ensure the header length is correct.
959        assert_eq!(
960            packet_builder.header_len(),
961            ETHERNET_MIN_HEADER_LENGTH + IPV4_MIN_HEADER_LENGTH + UDP_HEADER_LENGTH
962        );
963
964        // Ensure the payload is correct.
965        assert_eq!(
966            packet_builder.payload(),
967            &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
968        );
969
970        // Build the packet.
971        let packet = packet_builder.build();
972
973        // Parse the packet.
974        let parser = PacketParser::parse(&packet);
975
976        // Ensure the parser succeeded.
977        assert!(parser.is_ok());
978
979        // Unwrap the parser.
980        let parser = parser.unwrap();
981
982        // Ensure the parser contains an UDP header.
983        assert!(parser.udp.is_some());
984
985        // Unwrap the UDP header.
986        let udp = parser.udp.unwrap();
987
988        // Ensure the payload is correct.
989        assert_eq!(
990            udp.payload(),
991            &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
992        );
993    }
994
995    #[test]
996    fn misc() {
997        // Raw packet data.
998        let mut packet = [0u8; 64];
999
1000        // Measure the number of allocations.
1001        let allocations = allocation_counter::measure(|| {
1002            // Packet builder in the initial state.
1003            let packet_builder = PacketBuilder::new(&mut packet);
1004
1005            // Transition to the Ethernet header state.
1006            let eth_builder = packet_builder
1007                .ethernet(
1008                    &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1009                    &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
1010                    2054,
1011                )
1012                .unwrap();
1013
1014            // Ensure the header length is correct.
1015            assert_eq!(eth_builder.header_len(), ETHERNET_MIN_HEADER_LENGTH);
1016
1017            // Transition to the ARP header state.
1018            let arp_builder = eth_builder
1019                .arp(
1020                    1,
1021                    2048,
1022                    6,
1023                    4,
1024                    1,
1025                    &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1026                    &[192, 168, 1, 1],
1027                    &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
1028                    &[192, 168, 1, 2],
1029                )
1030                .unwrap();
1031
1032            // Ensure the header length is correct.
1033            assert_eq!(
1034                arp_builder.header_len(),
1035                ETHERNET_MIN_HEADER_LENGTH + ARP_HEADER_LENGTH
1036            );
1037
1038            // Ensure 64 (Raw) - 14 (Ethernet) - 28 (Arp) = 22.
1039            assert_eq!(arp_builder.payload_len(), 22);
1040        });
1041
1042        // Ensure zero allocations.
1043        assert_eq!(allocations.count_total, 0);
1044    }
1045
1046    #[test]
1047    fn arp_in_ethernet() {
1048        // Raw packet data.
1049        let mut packet = [0u8; 42];
1050
1051        // Expected output given the chosen values.
1052        let should_be = [
1053            255, 255, 255, 255, 255, 255, 52, 151, 246, 148, 2, 15, 8, 6, 0, 1, 8, 0, 6, 4, 0, 1,
1054            52, 151, 246, 148, 2, 15, 192, 168, 1, 1, 0, 0, 0, 0, 0, 0, 192, 168, 1, 2,
1055        ];
1056
1057        // Measure the number of allocations.
1058        let allocations = allocation_counter::measure(|| {
1059            // Packet builder.
1060            let packet_builder = PacketBuilder::new(&mut packet);
1061
1062            // Build the packet.
1063            packet_builder
1064                .ethernet(
1065                    &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1066                    &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
1067                    2054,
1068                )
1069                .unwrap()
1070                .arp(
1071                    1,
1072                    2048,
1073                    6,
1074                    4,
1075                    1,
1076                    &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1077                    &[192, 168, 1, 1],
1078                    &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
1079                    &[192, 168, 1, 2],
1080                )
1081                .unwrap();
1082        });
1083
1084        // Output should match the expectation.
1085        assert_eq!(packet, should_be);
1086
1087        // Ensure zero allocations.
1088        assert_eq!(allocations.count_total, 0);
1089    }
1090
1091    #[test]
1092    fn tcp_in_ipv4_in_ethernet() {
1093        // Raw packet data.
1094        let mut packet = [0u8; 54];
1095
1096        // Expected output given the chosen values.
1097        let should_be = [
1098            4, 180, 254, 154, 129, 199, 52, 151, 246, 148, 2, 15, 8, 0, 53, 143, 48, 57, 212, 49,
1099            112, 57, 123, 6, 87, 113, 192, 168, 1, 1, 192, 168, 1, 2, 0, 99, 0, 11, 0, 0, 0, 123,
1100            0, 0, 1, 65, 179, 99, 16, 225, 177, 80, 4, 210,
1101        ];
1102
1103        // Measure the number of allocations.
1104        let allocations = allocation_counter::measure(|| {
1105            // Packet builder.
1106            let packet_builder = PacketBuilder::new(&mut packet);
1107
1108            // Build the packet.
1109            packet_builder
1110                .ethernet(
1111                    &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1112                    &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1113                    2048,
1114                )
1115                .unwrap()
1116                .ipv4(
1117                    99,
1118                    5,
1119                    99,
1120                    123,
1121                    12345,
1122                    54321,
1123                    99,
1124                    12345,
1125                    123,
1126                    6,
1127                    &[192, 168, 1, 1],
1128                    &[192, 168, 1, 2],
1129                )
1130                .unwrap()
1131                .tcp(
1132                    &[192, 168, 1, 1],
1133                    99,
1134                    &[192, 168, 1, 2],
1135                    11,
1136                    123,
1137                    321,
1138                    11,
1139                    99,
1140                    99,
1141                    4321,
1142                    1234,
1143                    None,
1144                )
1145                .unwrap();
1146        });
1147
1148        // Output should match the expectation.
1149        assert_eq!(packet, should_be);
1150
1151        // Ensure zero allocations.
1152        assert_eq!(allocations.count_total, 0);
1153    }
1154
1155    #[test]
1156    fn udp_in_ipv4_in_ethernet() {
1157        // Raw packet data.
1158        let mut packet = [0u8; 54];
1159
1160        // Expected output given the chosen values.
1161        let should_be = [
1162            4, 180, 254, 154, 129, 199, 52, 151, 246, 148, 2, 15, 8, 0, 53, 143, 48, 57, 212, 49,
1163            112, 57, 123, 6, 87, 113, 192, 168, 1, 1, 192, 168, 1, 2, 0, 99, 0, 11, 16, 225, 107,
1164            55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1165        ];
1166
1167        // Measure the number of allocations.
1168        let allocations = allocation_counter::measure(|| {
1169            // Packet builder.
1170            let packet_builder = PacketBuilder::new(&mut packet);
1171
1172            // Build the packet.
1173            packet_builder
1174                .ethernet(
1175                    &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1176                    &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1177                    2048,
1178                )
1179                .unwrap()
1180                .ipv4(
1181                    99,
1182                    5,
1183                    99,
1184                    123,
1185                    12345,
1186                    54321,
1187                    99,
1188                    12345,
1189                    123,
1190                    6,
1191                    &[192, 168, 1, 1],
1192                    &[192, 168, 1, 2],
1193                )
1194                .unwrap()
1195                .udp(&[192, 168, 1, 1], 99, &[192, 168, 1, 2], 11, 4321, None)
1196                .unwrap();
1197        });
1198
1199        // Output should match the expectation.
1200        assert_eq!(packet, should_be);
1201
1202        // Ensure zero allocations.
1203        assert_eq!(allocations.count_total, 0);
1204    }
1205
1206    #[test]
1207    fn icmpv4_in_ipv4_in_ethernet() {
1208        // Raw packet data.
1209        let mut packet = [0u8; 64];
1210
1211        // Expected output given the chosen values.
1212        let should_be = [
1213            4, 180, 254, 154, 129, 199, 52, 151, 246, 148, 2, 15, 8, 0, 69, 143, 48, 57, 212, 49,
1214            112, 57, 123, 1, 71, 118, 192, 168, 1, 1, 192, 168, 1, 2, 8, 0, 247, 255, 0, 0, 0, 0,
1215            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1216        ];
1217
1218        // Measure the number of allocations.
1219        let allocations = allocation_counter::measure(|| {
1220            // Packet builder.
1221            let packet_builder = PacketBuilder::new(&mut packet);
1222
1223            // Build the packet.
1224            packet_builder
1225                .ethernet(
1226                    &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1227                    &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1228                    2048,
1229                )
1230                .unwrap()
1231                .ipv4(
1232                    4,
1233                    5,
1234                    99,
1235                    123,
1236                    12345,
1237                    54321,
1238                    99,
1239                    12345,
1240                    123,
1241                    1,
1242                    &[192, 168, 1, 1],
1243                    &[192, 168, 1, 2],
1244                )
1245                .unwrap()
1246                .icmpv4(8, 0, None)
1247                .unwrap();
1248        });
1249
1250        // Output should match the expectation.
1251        assert_eq!(packet, should_be);
1252
1253        // Ensure zero allocations.
1254        assert_eq!(allocations.count_total, 0);
1255    }
1256
1257    #[test]
1258    fn build_parse_ipv6() {
1259        // IPv6 source address.
1260        let src_addr = [
1261            0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70,
1262            0x73, 0x34,
1263        ];
1264
1265        // IPv6 destination address.
1266        let dest_addr = [
1267            0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0xb3, 0xff, 0xfe, 0x1e,
1268            0x83, 0x29,
1269        ];
1270
1271        // Raw packet data.
1272        let mut buffer = [0u8; 64];
1273
1274        // Build the packet.
1275        let packet = PacketBuilder::new(&mut buffer)
1276            .ethernet(
1277                &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1278                &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1279                34525,
1280            )
1281            .unwrap()
1282            .ipv6(6, 5, 4, 31, 17, 10, &src_addr, &dest_addr)
1283            .unwrap()
1284            .udp(&src_addr, 99, &dest_addr, 80, 10, None)
1285            .unwrap()
1286            .build();
1287
1288        // Expected output given the chosen values. Checksum should be (21, 45).
1289        assert_eq!(
1290            packet,
1291            [
1292                4, 180, 254, 154, 129, 199, 52, 151, 246, 148, 2, 15, 134, 221, 96, 80, 0, 4, 0,
1293                31, 17, 10, 32, 1, 13, 184, 133, 163, 0, 0, 0, 0, 138, 46, 3, 112, 115, 52, 254,
1294                128, 0, 0, 0, 0, 0, 0, 2, 2, 179, 255, 254, 30, 131, 41, 0, 99, 0, 80, 0, 10, 21,
1295                45, 0, 0
1296            ]
1297        );
1298
1299        // Parse the packet.
1300        let parser = PacketParser::parse(&packet);
1301
1302        // Ensure the parser is successful.
1303        assert!(parser.is_ok());
1304
1305        // Unwrap the parser.
1306        let unwrapped = parser.unwrap();
1307
1308        // Ensure the expected headers are present.
1309        assert!(unwrapped.ethernet.is_some());
1310        assert!(unwrapped.ipv6.is_some());
1311        assert!(unwrapped.udp.is_some());
1312
1313        // Ensure the unexpected headers are not present.
1314        assert!(unwrapped.arp.is_none());
1315        assert!(unwrapped.icmpv4.is_none());
1316        assert!(unwrapped.tcp.is_none());
1317    }
1318
1319    #[test]
1320    fn build_parse_qinq() {
1321        // Raw packet data.
1322        let mut buffer = [0u8; 64];
1323
1324        // Build a valid packet
1325        let packet = PacketBuilder::new(&mut buffer)
1326            // 22 bytes
1327            .ethernet_qinq(
1328                &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1329                &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1330                2048,
1331                200,
1332                100,
1333            )
1334            .unwrap()
1335            // 20 bytes
1336            .ipv4(
1337                4,
1338                5,
1339                99,
1340                123,
1341                42,
1342                54321,
1343                99,
1344                12345,
1345                123,
1346                17,
1347                &[192, 168, 1, 1],
1348                &[192, 168, 1, 2],
1349            )
1350            .unwrap()
1351            // 8 bytes
1352            .udp(&[192, 168, 1, 1], 99, &[192, 168, 1, 2], 11, 22, None)
1353            .unwrap()
1354            .build();
1355
1356        // Parse the packet.
1357        let parser = PacketParser::parse(&packet);
1358
1359        // Ensure the parser is successful.
1360        assert!(parser.is_ok());
1361
1362        // Unwrap the parser.
1363        let unwrapped = parser.unwrap();
1364
1365        // Ensure the expected headers are present.
1366        assert!(unwrapped.ethernet.is_some());
1367        assert!(unwrapped.ipv4.is_some());
1368        assert!(unwrapped.udp.is_some());
1369
1370        // Ensure the unexpected headers are not present.
1371        assert!(unwrapped.arp.is_none());
1372        assert!(unwrapped.icmpv4.is_none());
1373        assert!(unwrapped.tcp.is_none());
1374
1375        // Unwrap ethernet.
1376        let ethernet = unwrapped.ethernet.unwrap();
1377
1378        // Ensure expected VLAN tags are present.
1379        assert!(ethernet.vlan_tag().is_none());
1380        assert!(ethernet.double_vlan_tag().is_some());
1381
1382        // Ensure the expected fields are present.
1383        assert_eq!(ethernet.src_mac(), [0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f]);
1384        assert_eq!(ethernet.dest_mac(), [0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7]);
1385        assert_eq!(ethernet.ethertype(), 2048);
1386        assert_eq!(
1387            ethernet.double_vlan_tag().unwrap(),
1388            ((ETHERTYPE_QINQ, 200), (ETHERTYPE_VLAN, 100))
1389        );
1390    }
1391
1392    #[test]
1393    fn build_parse_qinq_icmpv6() {
1394        // Raw packet data.
1395        let mut buffer = [0u8; 70];
1396
1397        // IPv6 source address.
1398        let src_addr = [
1399            0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70,
1400            0x73, 0x34,
1401        ];
1402
1403        // IPv6 destination address.
1404        let dest_addr = [
1405            0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0xb3, 0xff, 0xfe, 0x1e,
1406            0x83, 0x29,
1407        ];
1408
1409        // Build a valid packet
1410        let packet = PacketBuilder::new(&mut buffer)
1411            // 22 bytes
1412            .ethernet_qinq(
1413                &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1414                &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1415                34525,
1416                200,
1417                100,
1418            )
1419            .unwrap()
1420            // 60 bytes
1421            .ipv6(6, 5, 4, 3, 58, 255, &src_addr, &dest_addr)
1422            .unwrap()
1423            // 8 bytes
1424            .icmpv6(&src_addr, &dest_addr, 128, 0, None)
1425            .unwrap()
1426            .build();
1427
1428        // Parse the packet.
1429        let parser = PacketParser::parse(&packet);
1430
1431        // Ensure the parser is successful.
1432        assert!(parser.is_ok());
1433
1434        // Unwrap the parser.
1435        let unwrapped = parser.unwrap();
1436
1437        // Ensure the expected headers are present.
1438        assert!(unwrapped.ethernet.is_some());
1439        assert!(unwrapped.ipv6.is_some());
1440        assert!(unwrapped.icmpv6.is_some());
1441
1442        // Ensure the unexpected headers are not present.
1443        assert!(unwrapped.arp.is_none());
1444        assert!(unwrapped.udp.is_none());
1445        assert!(unwrapped.tcp.is_none());
1446        assert!(unwrapped.icmpv4.is_none());
1447    }
1448
1449    #[test]
1450    pub fn build_parse_very_complex_packet() {
1451        // Raw packet data.
1452        let mut buffer = [0u8; 300];
1453
1454        // Build the packet.
1455        let packet = PacketBuilder::new(&mut buffer)
1456            .ethernet_qinq(
1457                &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1458                &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1459                34525,
1460                200,
1461                100,
1462            )
1463            .unwrap()
1464            .ipv6(6, 5, 4, 3, 0, 255, &[0; 16], &[0; 16])
1465            .unwrap()
1466            .hop_by_hop(60, 1, &[1; 8])
1467            .unwrap()
1468            .destination_options1(43, 1, &[1; 8])
1469            .unwrap()
1470            .routing_header(44, 1, 2, 3, &[2; 8])
1471            .unwrap()
1472            .fragment_header(51, 255, true, 0x04050607)
1473            .unwrap()
1474            .authentication_header(60, 2, 305419896, 2271560481, &[1; 8])
1475            .unwrap()
1476            .destination_options2(4, 1, &[1; 8])
1477            .unwrap()
1478            .ipv4(
1479                4,
1480                5,
1481                0,
1482                0,
1483                150,
1484                0,
1485                0,
1486                0,
1487                64,
1488                6,
1489                &[192, 168, 1, 1],
1490                &[192, 168, 1, 2],
1491            )
1492            .unwrap()
1493            .tcp(
1494                &[192, 168, 1, 1],
1495                99,
1496                &[192, 168, 1, 2],
1497                11,
1498                123,
1499                321,
1500                11,
1501                99,
1502                99,
1503                4321,
1504                1234,
1505                Some(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
1506            )
1507            .unwrap()
1508            .build();
1509
1510        // Parse the packet.
1511        let parser = PacketParser::parse(&packet);
1512
1513        // Ensure the parser is successful.
1514        assert!(parser.is_ok());
1515
1516        // Unwrap the parser.
1517        let unwrapped = parser.unwrap();
1518
1519        // Ensure the expected headers are present.
1520        assert!(unwrapped.ethernet.is_some());
1521        assert!(unwrapped.ipv6.is_some());
1522        assert!(unwrapped.ip_in_ip.is_some());
1523        assert!(unwrapped.tcp.is_some());
1524
1525        // Ensure the unexpected headers are not present.
1526        assert!(unwrapped.arp.is_none());
1527        assert!(unwrapped.udp.is_none());
1528        assert!(unwrapped.icmpv4.is_none());
1529        assert!(unwrapped.icmpv6.is_none());
1530
1531        // Unwrap IPv6.
1532        let ipv6 = unwrapped.ipv6.unwrap();
1533
1534        // Ensure extension headers are present.
1535        assert!(ipv6.extension_headers.is_some());
1536
1537        // Unwrap the extension headers.
1538        let extensions = ipv6.extension_headers.unwrap();
1539
1540        // Ensure the expected extension headers are present.
1541        assert!(extensions.hop_by_hop.is_some());
1542        assert!(extensions.destination_1st.is_some());
1543        assert!(extensions.routing.is_some());
1544        assert!(extensions.fragment.is_some());
1545        assert!(extensions.auth_header.is_some());
1546        assert!(extensions.destination_2nd.is_some());
1547
1548        // Unwrap the IP-in-IP.
1549        let ip_in_ip = unwrapped.ip_in_ip.unwrap();
1550
1551        // Ensure the expected headers are present.
1552        assert!(match ip_in_ip {
1553            IpInIp::Ipv4(_) => true,
1554            _ => false,
1555        });
1556    }
1557}