Thanks to visit codestin.com
Credit goes to docs.rs

etherparse/
packet_builder.rs

1use crate::err::packet::BuildWriteError;
2
3use super::*;
4
5use std::{io, marker};
6
7/// Helper for building packets.
8///
9/// The packet builder allows the easy construction of a packet from the
10/// ethernet II layer downwards including ipv6, ipv4, the udp header and the
11/// actual payload. The packet builder automatically calculates lengths & checksums
12/// for ip & udp and set type identifiers for ethernetII and ip. This makes it
13/// easy and less error prone to construct custom packets.
14///
15/// # Example:
16///
17/// Generating a packet that starts with an Ethernet II header:
18///
19/// ```
20/// use etherparse::PacketBuilder;
21///
22/// let builder = PacketBuilder::
23///     ethernet2([1,2,3,4,5,6],     //source mac
24///               [7,8,9,10,11,12]) //destination mac
25///    .ipv4([192,168,1,1], //source ip
26///          [192,168,1,2], //destination ip
27///          20)            //time to life
28///    .udp(21,    //source port
29///         1234); //destination port
30///
31/// //payload of the udp packet
32/// let payload = [1,2,3,4,5,6,7,8];
33///
34/// //get some memory to store the result
35/// let mut result = Vec::<u8>::with_capacity(
36///                     builder.size(payload.len()));
37///
38/// //serialize
39/// builder.write(&mut result, &payload).unwrap();
40/// println!("{:?}", result);
41/// ```
42///
43/// # Options
44///
45/// * Starting Options:
46///     * [`PacketBuilder::ethernet2`]
47///     * [`PacketBuilder::linux_sll`]
48///     * [`PacketBuilder::ip`]
49///     * [`PacketBuilder::ipv4`]
50///     * [`PacketBuilder::ipv6`]
51/// * Options after an Ethernet2 header was added:
52///     * [`PacketBuilderStep<Ethernet2Header>::arp`]
53///     * [`PacketBuilderStep<Ethernet2Header>::vlan`]
54///     * [`PacketBuilderStep<Ethernet2Header>::single_vlan`]
55///     * [`PacketBuilderStep<Ethernet2Header>::double_vlan`]
56///     * [`PacketBuilderStep<Ethernet2Header>::ip`]
57///     * [`PacketBuilderStep<Ethernet2Header>::ipv4`]
58///     * [`PacketBuilderStep<Ethernet2Header>::ipv6`]
59/// * Options after a Linux Cooked Capture v1 (SLL) was added:
60///     * [`PacketBuilderStep<LinuxSllHeader>::ip`]
61///     * [`PacketBuilderStep<LinuxSllHeader>::ipv4`]
62///     * [`PacketBuilderStep<LinuxSllHeader>::ipv6`]
63/// * Options after an Vlan header was added:
64///     * [`PacketBuilderStep<VlanHeader>::ip`]
65///     * [`PacketBuilderStep<VlanHeader>::ipv4`]
66///     * [`PacketBuilderStep<VlanHeader>::ipv6`]
67/// * Options after an IP header was added:
68///     * [`PacketBuilderStep<IpHeaders>::write`]
69///     * [`PacketBuilderStep<IpHeaders>::tcp`]
70///     * [`PacketBuilderStep<IpHeaders>::udp`]
71///     * [`PacketBuilderStep<IpHeaders>::icmpv4`]
72///     * [`PacketBuilderStep<IpHeaders>::icmpv4_raw`]
73///     * [`PacketBuilderStep<IpHeaders>::icmpv4_echo_request`]
74///     * [`PacketBuilderStep<IpHeaders>::icmpv4_echo_reply`]
75///     * [`PacketBuilderStep<IpHeaders>::icmpv6`]
76///     * [`PacketBuilderStep<IpHeaders>::icmpv6_raw`]
77///     * [`PacketBuilderStep<IpHeaders>::icmpv6_echo_request`]
78///     * [`PacketBuilderStep<IpHeaders>::icmpv6_echo_reply`]
79/// * Options after an TCP header was added:
80///     * [`PacketBuilderStep<TcpHeader>::write`]
81///     * [`PacketBuilderStep<TcpHeader>::size`]
82///     * [`PacketBuilderStep<TcpHeader>::ns`]
83///     * [`PacketBuilderStep<TcpHeader>::fin`]
84///     * [`PacketBuilderStep<TcpHeader>::syn`]
85///     * [`PacketBuilderStep<TcpHeader>::rst`]
86///     * [`PacketBuilderStep<TcpHeader>::psh`]
87///     * [`PacketBuilderStep<TcpHeader>::ack`]
88///     * [`PacketBuilderStep<TcpHeader>::urg`]
89///     * [`PacketBuilderStep<TcpHeader>::ece`]
90///     * [`PacketBuilderStep<TcpHeader>::cwr`]
91///     * [`PacketBuilderStep<TcpHeader>::options`]
92///     * [`PacketBuilderStep<TcpHeader>::options_raw`]
93/// * Options after an UDP header was added:
94///     * [`PacketBuilderStep<UdpHeader>::write`]
95///     * [`PacketBuilderStep<UdpHeader>::size`]
96/// * Options after an ICMPv4 header was added:
97///     * [`PacketBuilderStep<Icmpv4Header>::write`]
98///     * [`PacketBuilderStep<Icmpv4Header>::size`]
99/// * Options after an ICMPv6 header was added:
100///     * [`PacketBuilderStep<Icmpv6Header>::write`]
101///     * [`PacketBuilderStep<Icmpv6Header>::size`]
102///
103#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
104pub struct PacketBuilder {}
105
106impl PacketBuilder {
107    /// Start an packet with an ethernetII header.
108    ///
109    /// # Example
110    ///
111    /// Basic usage:
112    ///
113    /// ```
114    /// # use etherparse::PacketBuilder;
115    /// #
116    /// let builder = PacketBuilder::
117    ///     ethernet2([1,2,3,4,5,6],     //source mac
118    ///               [7,8,9,10,11,12]) //destination mac
119    ///    .ipv4([192,168,1,1], //source ip
120    ///          [192,168,1,2], //destination ip
121    ///          20)            //time to life
122    ///    .udp(21,    //source port
123    ///         1234); //destination port
124    ///
125    /// //payload of the udp packet
126    /// let payload = [1,2,3,4,5,6,7,8];
127    ///
128    /// //get some memory to store the result
129    /// let mut result = Vec::<u8>::with_capacity(
130    ///                     builder.size(payload.len()));
131    ///
132    /// //serialize
133    /// builder.write(&mut result, &payload).unwrap();
134    /// ```
135    pub fn ethernet2(source: [u8; 6], destination: [u8; 6]) -> PacketBuilderStep<Ethernet2Header> {
136        PacketBuilderStep {
137            state: PacketImpl {
138                link_header: Some(LinkHeader::Ethernet2(Ethernet2Header {
139                    source,
140                    destination,
141                    ether_type: EtherType(0), //the type identifier
142                })),
143                vlan_header: None,
144                net_header: None,
145                transport_header: None,
146            },
147            _marker: marker::PhantomData::<Ethernet2Header> {},
148        }
149    }
150
151    /// Start an packet with an Linux Cooked Capture (v1) header.
152    ///
153    /// # Example
154    ///
155    /// Basic usage:
156    ///
157    /// ```
158    /// # use etherparse::{PacketBuilder, LinuxSllPacketType};
159    /// #
160    /// let builder = PacketBuilder::
161    ///     linux_sll(LinuxSllPacketType::OTHERHOST, //packet type
162    ///               6, //sender address valid length
163    ///               [1,2,3,4,5,6,0,0]) //sender address with padding
164    ///    .ipv4([192,168,1,1], //source ip
165    ///          [192,168,1,2], //destination ip
166    ///          20)            //time to life
167    ///    .udp(21,    //source port
168    ///         1234); //destination port
169    ///
170    /// //payload of the udp packet
171    /// let payload = [1,2,3,4,5,6,7,8];
172    ///
173    /// //get some memory to store the result
174    /// let mut result = Vec::<u8>::with_capacity(
175    ///                     builder.size(payload.len()));
176    ///
177    /// //serialize
178    /// builder.write(&mut result, &payload).unwrap();
179    /// ```
180    pub fn linux_sll(
181        packet_type: LinuxSllPacketType,
182        sender_address_valid_length: u16,
183        sender_address: [u8; 8],
184    ) -> PacketBuilderStep<LinuxSllHeader> {
185        PacketBuilderStep {
186            state: PacketImpl {
187                link_header: Some(LinkHeader::LinuxSll(LinuxSllHeader {
188                    packet_type,
189                    arp_hrd_type: ArpHardwareId::ETHERNET,
190                    sender_address_valid_length,
191                    sender_address,
192                    protocol_type: LinuxSllProtocolType::EtherType(EtherType(0)), // Will be overwritten when writing depending on the net layer
193                })),
194                vlan_header: None,
195                net_header: None,
196                transport_header: None,
197            },
198            _marker: marker::PhantomData::<LinuxSllHeader> {},
199        }
200    }
201
202    /// Starts a packet with an IPv4 header.
203    ///
204    /// # Example
205    ///
206    /// Basic usage:
207    ///
208    /// ```
209    /// # use etherparse::PacketBuilder;
210    /// #
211    /// let builder = PacketBuilder::
212    ///    ipv4([192,168,1,1],  //source ip
213    ///          [192,168,1,2], //destination ip
214    ///          20)            //time to life
215    ///    .udp(21,    //source port
216    ///         1234); //destination port
217    ///
218    /// //payload of the udp packet
219    /// let payload = [1,2,3,4,5,6,7,8];
220    ///     
221    /// //get some memory to store the result
222    /// let mut result = Vec::<u8>::with_capacity(
223    ///                     builder.size(payload.len()));
224    ///
225    /// //serialize
226    /// builder.write(&mut result, &payload).unwrap();
227    /// ```
228    pub fn ipv4(
229        source: [u8; 4],
230        destination: [u8; 4],
231        time_to_live: u8,
232    ) -> PacketBuilderStep<IpHeaders> {
233        PacketBuilderStep {
234            state: PacketImpl {
235                link_header: None,
236                vlan_header: None,
237                net_header: None,
238                transport_header: None,
239            },
240            _marker: marker::PhantomData::<Ethernet2Header> {},
241        }
242        .ipv4(source, destination, time_to_live)
243    }
244
245    /// Start a packet with an IPv6 header.
246    ///
247    /// # Example
248    ///
249    /// Basic usage:
250    ///
251    /// ```
252    /// # use etherparse::PacketBuilder;
253    /// #
254    /// let builder = PacketBuilder::
255    ///     ipv6(
256    ///         //source
257    ///         [11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
258    ///         //destination
259    ///         [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],
260    ///         //hop_limit
261    ///         47)
262    ///    .udp(21,    //source port
263    ///         1234); //destination port
264    ///
265    /// //payload of the udp packet
266    /// let payload = [1,2,3,4,5,6,7,8];
267    ///
268    /// //get some memory to store the result
269    /// let mut result = Vec::<u8>::with_capacity(
270    ///                     builder.size(payload.len()));
271    ///
272    /// //serialize
273    /// builder.write(&mut result, &payload).unwrap();
274    /// ```
275    pub fn ipv6(
276        source: [u8; 16],
277        destination: [u8; 16],
278        hop_limit: u8,
279    ) -> PacketBuilderStep<IpHeaders> {
280        PacketBuilderStep {
281            state: PacketImpl {
282                link_header: None,
283                vlan_header: None,
284                net_header: None,
285                transport_header: None,
286            },
287            _marker: marker::PhantomData::<Ethernet2Header> {},
288        }
289        .ipv6(source, destination, hop_limit)
290    }
291
292    /// Starts a packet with an arbitrary IP header (length, protocol/next_header & checksum fields will be overwritten based on the rest of the packet).
293    ///
294    /// # Examples
295    ///
296    /// With an IPv4 header:
297    ///
298    /// ```
299    /// # use etherparse::*;
300    /// #
301    /// let builder = PacketBuilder::
302    ///    //payload_len, protocol & checksum will be replaced during write
303    ///    ip(IpHeaders::Ipv4(
304    ///        Ipv4Header::new(
305    ///            0, //payload_len will be replaced during write
306    ///            12, //time_to_live
307    ///            ip_number::UDP, //will be replaced during write
308    ///            [0,1,2,3], //source
309    ///            [4,5,6,7] //destination
310    ///        ).unwrap(),
311    ///        Default::default()))
312    ///    .udp(21,    //source port
313    ///         1234); //destination port
314    ///
315    /// //payload of the udp packet
316    /// let payload = [1,2,3,4,5,6,7,8];
317    ///
318    /// //get some memory to store the result
319    /// let mut result = Vec::<u8>::with_capacity(
320    ///                     builder.size(payload.len()));
321    ///
322    /// //serialize
323    /// builder.write(&mut result, &payload).unwrap();
324    /// ```
325    ///
326    /// With an IPv6 header:
327    ///
328    /// ```
329    /// # use etherparse::*;
330    /// #
331    /// let builder = PacketBuilder::
332    ///    ip(IpHeaders::Ipv6(
333    ///         Ipv6Header{
334    ///             traffic_class: 0,
335    ///             flow_label: 0.try_into().unwrap(),
336    ///             hop_limit: 4.try_into().unwrap(),
337    ///             source: [0;16],
338    ///             destination: [0;16],
339    ///             // payload_length & next_header will be replaced during write
340    ///             ..Default::default()
341    ///         },
342    ///         Default::default()))
343    ///    .udp(21,    //source port
344    ///         1234); //destination port
345    ///
346    /// //payload of the udp packet
347    /// let payload = [1,2,3,4,5,6,7,8];
348    ///     
349    /// //get some memory to store the result
350    /// let mut result = Vec::<u8>::with_capacity(
351    ///                     builder.size(payload.len()));
352    ///
353    /// //serialize
354    /// builder.write(&mut result, &payload).unwrap();
355    /// ```
356    pub fn ip(ip_header: IpHeaders) -> PacketBuilderStep<IpHeaders> {
357        PacketBuilderStep {
358            state: PacketImpl {
359                link_header: None,
360                vlan_header: None,
361                net_header: None,
362                transport_header: None,
363            },
364            _marker: marker::PhantomData::<Ethernet2Header> {},
365        }
366        .ip(ip_header)
367    }
368}
369
370struct PacketImpl {
371    link_header: Option<LinkHeader>,
372    net_header: Option<NetHeaders>,
373    vlan_header: Option<VlanHeader>,
374    transport_header: Option<TransportHeader>,
375}
376
377///An unfinished packet that is build with the packet builder
378#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
379pub struct PacketBuilderStep<LastStep> {
380    state: PacketImpl,
381    _marker: marker::PhantomData<LastStep>,
382}
383
384#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
385impl PacketBuilderStep<Ethernet2Header> {
386    /// Add an IPv4 header
387    ///
388    /// # Example
389    ///
390    /// Basic usage:
391    ///
392    /// ```
393    /// # use etherparse::PacketBuilder;
394    /// #
395    /// let builder = PacketBuilder::
396    ///     ethernet2([1,2,3,4,5,6],     //source mac
397    ///               [7,8,9,10,11,12]) //destination mac
398    ///    .ipv4([192,168,1,1], //source ip
399    ///          [192,168,1,2], //destination ip
400    ///          20)            //time to life
401    ///    .udp(21,    //source port
402    ///         1234); //destination port
403    ///
404    /// //payload of the udp packet
405    /// let payload = [1,2,3,4,5,6,7,8];
406    ///
407    /// //get some memory to store the result
408    /// let mut result = Vec::<u8>::with_capacity(
409    ///                     builder.size(payload.len()));
410    ///
411    /// //serialize
412    /// builder.write(&mut result, &payload).unwrap();
413    /// ```
414    pub fn ipv4(
415        mut self,
416        source: [u8; 4],
417        destination: [u8; 4],
418        time_to_live: u8,
419    ) -> PacketBuilderStep<IpHeaders> {
420        //add ip header
421        self.state.net_header = Some(NetHeaders::Ipv4(
422            Ipv4Header {
423                source,
424                destination,
425                time_to_live,
426                ..Default::default()
427            },
428            Default::default(),
429        ));
430        //return for next step
431        PacketBuilderStep {
432            state: self.state,
433            _marker: marker::PhantomData::<IpHeaders> {},
434        }
435    }
436
437    /// Add an IP header (length, protocol/next_header & checksum fields will be overwritten based on the rest of the packet).
438    ///
439    /// # Examples
440    ///
441    /// With an IPv4 header:
442    ///
443    /// ```
444    /// # use etherparse::*;
445    /// #
446    /// let builder = PacketBuilder::
447    ///     ethernet2([1,2,3,4,5,6],
448    ///               [7,8,9,10,11,12])
449    ///    //payload_len, protocol & checksum will be replaced during write
450    ///    .ip(IpHeaders::Ipv4(
451    ///        Ipv4Header::new(
452    ///            0, //payload_len will be replaced during write
453    ///            12, //time_to_live
454    ///            ip_number::UDP, //will be replaced during write
455    ///            [0,1,2,3], //source
456    ///            [4,5,6,7] //destination
457    ///        ).unwrap(),
458    ///        Default::default()));
459    /// ```
460    ///
461    /// With an IPv6 header:
462    ///
463    /// ```
464    /// # use etherparse::*;
465    /// #
466    /// let builder = PacketBuilder::
467    ///     ethernet2([1,2,3,4,5,6],
468    ///               [7,8,9,10,11,12])
469    ///    .ip(IpHeaders::Ipv6(
470    ///         Ipv6Header{
471    ///             traffic_class: 0,
472    ///             flow_label: 0.try_into().unwrap(),
473    ///             hop_limit: 4,
474    ///             source: [0;16],
475    ///             destination: [0;16],
476    ///             // payload_length & next_header will be replaced during write
477    ///             ..Default::default()
478    ///         },
479    ///         Default::default()));
480    /// ```
481    pub fn ip(mut self, ip_header: IpHeaders) -> PacketBuilderStep<IpHeaders> {
482        //add ip header
483        self.state.net_header = Some(match ip_header {
484            IpHeaders::Ipv4(header, exts) => NetHeaders::Ipv4(header, exts),
485            IpHeaders::Ipv6(header, exts) => NetHeaders::Ipv6(header, exts),
486        });
487        //return for next step
488        PacketBuilderStep {
489            state: self.state,
490            _marker: marker::PhantomData::<IpHeaders> {},
491        }
492    }
493
494    /// Add an IPv6 header
495    ///
496    /// # Example
497    ///
498    /// Basic usage:
499    ///
500    /// ```
501    /// # use etherparse::PacketBuilder;
502    /// #
503    /// let builder = PacketBuilder::
504    ///     ethernet2([1,2,3,4,5,6],
505    ///               [7,8,9,10,11,12])
506    ///     .ipv6(
507    ///         //source
508    ///         [11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
509    ///         //destination
510    ///         [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],
511    ///         //hop_limit
512    ///         47)
513    ///    .udp(21,    //source port
514    ///         1234); //destination port
515    ///
516    /// //payload of the udp packet
517    /// let payload = [1,2,3,4,5,6,7,8];
518    ///
519    /// //get some memory to store the result
520    /// let mut result = Vec::<u8>::with_capacity(
521    ///                     builder.size(payload.len()));
522    ///
523    /// //serialize
524    /// builder.write(&mut result, &payload).unwrap();
525    /// ```
526    pub fn ipv6(
527        mut self,
528        source: [u8; 16],
529        destination: [u8; 16],
530        hop_limit: u8,
531    ) -> PacketBuilderStep<IpHeaders> {
532        self.state.net_header = Some(NetHeaders::Ipv6(
533            Ipv6Header {
534                traffic_class: 0,
535                flow_label: Ipv6FlowLabel::ZERO,
536                payload_length: 0,          //filled in on write
537                next_header: IpNumber(255), //filled in on write
538                hop_limit,
539                source,
540                destination,
541            },
542            Default::default(),
543        ));
544
545        //return for next step
546        PacketBuilderStep {
547            state: self.state,
548            _marker: marker::PhantomData::<IpHeaders> {},
549        }
550    }
551
552    /// Adds a vlan tagging header with the given vlan identifier
553    ///
554    /// # Example
555    ///
556    /// Basic usage:
557    ///
558    /// ```
559    /// # use etherparse::{PacketBuilder, SingleVlanHeader, VlanHeader};
560    /// #
561    /// let builder = PacketBuilder::
562    ///     ethernet2([1,2,3,4,5,6],     //source mac
563    ///               [7,8,9,10,11,12]) //destination mac
564    ///     .vlan(VlanHeader::Single(
565    ///         SingleVlanHeader{
566    ///             pcp: 1.try_into().unwrap(),
567    ///             drop_eligible_indicator: false,
568    ///             vlan_id: 0x123.try_into().unwrap(),
569    ///             ether_type: 0.into() // will be overwritten during write
570    ///         }))
571    ///     .ipv4([192,168,1,1], //source ip
572    ///           [192,168,1,2], //destination ip
573    ///           20)            //time to life
574    ///     .udp(21,    //source port
575    ///          1234); //destination port
576    ///
577    /// //payload of the udp packet
578    /// let payload = [1,2,3,4,5,6,7,8];
579    ///
580    /// //get some memory to store the result
581    /// let mut result = Vec::<u8>::with_capacity(
582    ///                     builder.size(payload.len()));
583    ///
584    /// //serialize
585    /// builder.write(&mut result, &payload).unwrap();
586    /// ```
587    pub fn vlan(mut self, vlan: VlanHeader) -> PacketBuilderStep<VlanHeader> {
588        self.state.vlan_header = Some(vlan);
589        //return for next step
590        PacketBuilderStep {
591            state: self.state,
592            _marker: marker::PhantomData::<VlanHeader> {},
593        }
594    }
595
596    /// Adds a vlan tagging header with the given vlan identifier
597    ///
598    /// # Example
599    ///
600    /// Basic usage:
601    ///
602    /// ```
603    /// # use etherparse::{PacketBuilder, SingleVlanHeader, VlanHeader};
604    /// #
605    /// let builder = PacketBuilder::
606    ///     ethernet2([1,2,3,4,5,6],     //source mac
607    ///               [7,8,9,10,11,12]) //destination mac
608    ///     .single_vlan(0x123.try_into().unwrap()) // vlan identifier
609    ///     .ipv4([192,168,1,1], //source ip
610    ///           [192,168,1,2], //destination ip
611    ///           20)            //time to life
612    ///     .udp(21,    //source port
613    ///          1234); //destination port
614    ///
615    /// //payload of the udp packet
616    /// let payload = [1,2,3,4,5,6,7,8];
617    ///
618    /// //get some memory to store the result
619    /// let mut result = Vec::<u8>::with_capacity(
620    ///                     builder.size(payload.len()));
621    ///
622    /// //serialize
623    /// builder.write(&mut result, &payload).unwrap();
624    /// ```
625    pub fn single_vlan(mut self, vlan_identifier: VlanId) -> PacketBuilderStep<VlanHeader> {
626        self.state.vlan_header = Some(VlanHeader::Single(SingleVlanHeader {
627            pcp: VlanPcp::ZERO,
628            drop_eligible_indicator: false,
629            vlan_id: vlan_identifier,
630            ether_type: EtherType(0), //will be set automatically during write
631        }));
632        //return for next step
633        PacketBuilderStep {
634            state: self.state,
635            _marker: marker::PhantomData::<VlanHeader> {},
636        }
637    }
638
639    /// Adds two vlan tagging header with the given vlan identifiers (also known as double vlan tagging).
640    ///
641    /// # Example
642    ///
643    /// Basic usage:
644    ///
645    /// ```
646    /// # use etherparse::{PacketBuilder, SingleVlanHeader, VlanHeader};
647    /// #
648    /// let builder = PacketBuilder::
649    ///     ethernet2([1,2,3,4,5,6],     //source mac
650    ///               [7,8,9,10,11,12]) //destination mac
651    ///     .double_vlan(0x123.try_into().unwrap(), // outer vlan identifier
652    ///                  0x234.try_into().unwrap()) // inner vlan identifier
653    ///     .ipv4([192,168,1,1], //source ip
654    ///           [192,168,1,2], //destination ip
655    ///           20)            //time to life
656    ///     .udp(21,    //source port
657    ///          1234); //destination port
658    ///
659    /// //payload of the udp packet
660    /// let payload = [1,2,3,4,5,6,7,8];
661    ///
662    /// //get some memory to store the result
663    /// let mut result = Vec::<u8>::with_capacity(
664    ///                     builder.size(payload.len()));
665    ///
666    /// //serialize
667    /// builder.write(&mut result, &payload).unwrap();
668    /// ```
669    pub fn double_vlan(
670        mut self,
671        outer_vlan_identifier: VlanId,
672        inner_vlan_identifier: VlanId,
673    ) -> PacketBuilderStep<VlanHeader> {
674        self.state.vlan_header = Some(VlanHeader::Double(DoubleVlanHeader {
675            outer: SingleVlanHeader {
676                pcp: VlanPcp::ZERO,
677                drop_eligible_indicator: false,
678                vlan_id: outer_vlan_identifier,
679                ether_type: EtherType(0), //will be set automatically during write
680            },
681            inner: SingleVlanHeader {
682                pcp: VlanPcp::ZERO,
683                drop_eligible_indicator: false,
684                vlan_id: inner_vlan_identifier,
685                ether_type: EtherType(0), //will be set automatically during write
686            },
687        }));
688        //return for next step
689        PacketBuilderStep {
690            state: self.state,
691            _marker: marker::PhantomData::<VlanHeader> {},
692        }
693    }
694
695    /// Adds an ARP packet.
696    ///
697    /// # Example
698    ///
699    /// Basic usage:
700    ///
701    /// ```
702    /// use etherparse::*;
703    ///
704    /// let builder = PacketBuilder::
705    ///     ethernet2([1,2,3,4,5,6],    // source mac
706    ///               [7,8,9,10,11,12]) // destination mac
707    ///     .arp(ArpPacket::new(
708    ///         ArpHardwareId::ETHERNET,
709    ///         EtherType::IPV4,
710    ///         ArpOperation::REQUEST,
711    ///         &[1,2,3,4,5,6], // sender_hw_addr
712    ///         &[7,6,8,9],     // sender_protocol_addr
713    ///         &[10,11,12,14,15,16], // target_hw_addr
714    ///         &[17,18,19,20]        // target_protocol_addr
715    ///     ).unwrap());
716    ///
717    /// // get some memory to store the result
718    /// let mut result = Vec::<u8>::with_capacity(builder.size());
719    ///
720    /// // serialize
721    /// builder.write(&mut result).unwrap();
722    /// ```
723    pub fn arp(mut self, arp_packet: ArpPacket) -> PacketBuilderStep<ArpPacket> {
724        self.state.net_header = Some(NetHeaders::Arp(arp_packet));
725        //return for next step
726        PacketBuilderStep {
727            state: self.state,
728            _marker: marker::PhantomData::<ArpPacket> {},
729        }
730    }
731}
732
733#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
734impl PacketBuilderStep<LinuxSllHeader> {
735    /// Add an ip header (length, protocol/next_header & checksum fields will be overwritten based on the rest of the packet).
736    ///
737    /// # Example IPv4
738    /// ```
739    /// # use etherparse::*;
740    /// #
741    /// let builder = PacketBuilder::
742    ///     linux_sll(LinuxSllPacketType::OTHERHOST, //packet type
743    ///               6, //sender address valid length
744    ///               [1,2,3,4,5,6,0,0]) //sender address with padding
745    ///    //payload_len, protocol & checksum will be replaced during write
746    ///    .ip(IpHeaders::Ipv4(
747    ///         Ipv4Header::new(
748    ///             0, //payload_len will be replaced during write
749    ///             12, //time_to_live
750    ///             ip_number::UDP, //will be replaced during write
751    ///             [0,1,2,3], //source
752    ///             [4,5,6,7] //destination
753    ///         ).unwrap(),
754    ///         Default::default() // IPv4 extension headers (default is none)
755    ///     ));
756    /// ```
757    ///
758    /// # Example IPv6
759    /// ```
760    /// # use etherparse::*;
761    /// #
762    /// let builder = PacketBuilder::
763    ///     linux_sll(LinuxSllPacketType::OTHERHOST, //packet type
764    ///               6, //sender address valid length
765    ///               [1,2,3,4,5,6,0,0]) //sender address with padding
766    ///    .ip(IpHeaders::Ipv6(
767    ///         Ipv6Header{
768    ///             traffic_class: 0,
769    ///             flow_label: 0.try_into().unwrap(),
770    ///             hop_limit: 4,
771    ///             source: [0;16],
772    ///             destination: [0;16],
773    ///             // payload_length & next_header will be replaced during write
774    ///             ..Default::default()
775    ///         },
776    ///         Default::default() // IPv6 extension headers (default is none)
777    ///     ));
778    /// ```
779    pub fn ip(self, ip_header: IpHeaders) -> PacketBuilderStep<IpHeaders> {
780        //use the method from the Ethernet2Header implementation
781        PacketBuilderStep {
782            state: self.state,
783            _marker: marker::PhantomData::<Ethernet2Header> {},
784        }
785        .ip(ip_header)
786    }
787
788    /// Add an IPv6 header
789    ///
790    /// # Example
791    ///
792    /// Basic usage:
793    ///
794    /// ```
795    /// # use etherparse::{PacketBuilder, LinuxSllPacketType, ArpHardwareId, LinuxSllProtocolType, EtherType};
796    /// #
797    /// let builder = PacketBuilder::
798    ///     linux_sll(LinuxSllPacketType::OTHERHOST, //packet type
799    ///               6, //sender address valid length
800    ///               [1,2,3,4,5,6,0,0]) //sender address with padding
801    ///     .ipv6(
802    ///         //source
803    ///         [11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
804    ///         //destination
805    ///         [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],
806    ///         //hop_limit
807    ///         47)
808    ///     .udp(21,    //source port
809    ///          1234); //destination port
810    ///
811    /// //payload of the udp packet
812    /// let payload = [1,2,3,4,5,6,7,8];
813    ///
814    /// //get some memory to store the result
815    /// let mut result = Vec::<u8>::with_capacity(
816    ///                     builder.size(payload.len()));
817    ///
818    /// //serialize
819    /// builder.write(&mut result, &payload).unwrap();
820    /// ```
821    pub fn ipv6(
822        self,
823        source: [u8; 16],
824        destination: [u8; 16],
825        hop_limit: u8,
826    ) -> PacketBuilderStep<IpHeaders> {
827        //use the method from the Ethernet2Header implementation
828        PacketBuilderStep {
829            state: self.state,
830            _marker: marker::PhantomData::<Ethernet2Header> {},
831        }
832        .ipv6(source, destination, hop_limit)
833    }
834
835    /// Add an IPv4 header
836    ///
837    /// # Example
838    ///
839    /// Basic usage:
840    ///
841    /// ```
842    /// # use etherparse::{PacketBuilder, LinuxSllPacketType, ArpHardwareId, LinuxSllProtocolType, EtherType};
843    /// #
844    /// let builder = PacketBuilder::
845    ///     linux_sll(LinuxSllPacketType::OTHERHOST, //packet type
846    ///               6, //sender address valid length
847    ///               [1,2,3,4,5,6,0,0]) //sender address with padding
848    ///     .ipv4([192,168,1,1], //source ip
849    ///           [192,168,1,2], //destination ip
850    ///           20)            //time to life
851    ///     .udp(21,    //source port
852    ///          1234); //destination port
853    ///
854    /// //payload of the udp packet
855    /// let payload = [1,2,3,4,5,6,7,8];
856    ///
857    /// //get some memory to store the result
858    /// let mut result = Vec::<u8>::with_capacity(
859    ///                     builder.size(payload.len()));
860    ///
861    /// //serialize
862    /// builder.write(&mut result, &payload).unwrap();
863    /// ```
864    pub fn ipv4(
865        self,
866        source: [u8; 4],
867        destination: [u8; 4],
868        time_to_live: u8,
869    ) -> PacketBuilderStep<IpHeaders> {
870        //use the method from the Ethernet2Header implementation
871        PacketBuilderStep {
872            state: self.state,
873            _marker: marker::PhantomData::<Ethernet2Header> {},
874        }
875        .ipv4(source, destination, time_to_live)
876    }
877
878    /// Adds an ARP packet.
879    ///
880    /// # Example
881    ///
882    /// Basic usage:
883    ///
884    /// ```
885    /// use etherparse::*;
886    ///
887    /// let builder = PacketBuilder::
888    ///     linux_sll(LinuxSllPacketType::OTHERHOST, //packet type
889    ///               6, //sender address valid length
890    ///               [1,2,3,4,5,6,0,0]) //sender address with padding
891    ///     .arp(ArpPacket::new(
892    ///         ArpHardwareId::ETHERNET,
893    ///         EtherType::IPV4,
894    ///         ArpOperation::REQUEST,
895    ///         &[1,2,3,4,5,6], // sender_hw_addr
896    ///         &[7,6,8,9],     // sender_protocol_addr
897    ///         &[10,11,12,14,15,16], // target_hw_addr
898    ///         &[17,18,19,20]        // target_protocol_addr
899    ///     ).unwrap());
900    ///
901    /// // get some memory to store the result
902    /// let mut result = Vec::<u8>::with_capacity(builder.size());
903    ///
904    /// // serialize
905    /// builder.write(&mut result).unwrap();
906    /// ```
907    pub fn arp(mut self, arp_packet: ArpPacket) -> PacketBuilderStep<ArpPacket> {
908        self.state.net_header = Some(NetHeaders::Arp(arp_packet));
909        // return for next step
910        PacketBuilderStep {
911            state: self.state,
912            _marker: marker::PhantomData::<ArpPacket> {},
913        }
914    }
915}
916
917#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
918impl PacketBuilderStep<VlanHeader> {
919    ///Add an ip header (length, protocol/next_header & checksum fields will be overwritten based on the rest of the packet).
920    ///
921    /// # Example IPv4
922    /// ```
923    /// # use etherparse::*;
924    /// #
925    /// let builder = PacketBuilder::
926    ///     ethernet2([1,2,3,4,5,6],
927    ///               [7,8,9,10,11,12])
928    ///    .single_vlan(0x132.try_into().unwrap())
929    ///    //payload_len, protocol & checksum will be replaced during write
930    ///    .ip(IpHeaders::Ipv4(
931    ///         Ipv4Header::new(
932    ///             0, //payload_len will be replaced during write
933    ///             12, //time_to_live
934    ///             ip_number::UDP, //will be replaced during write
935    ///             [0,1,2,3], //source
936    ///             [4,5,6,7] //destination
937    ///         ).unwrap(),
938    ///         Default::default() // IPv4 extension headers (default is none)
939    ///     ));
940    /// ```
941    ///
942    /// # Example IPv6
943    /// ```
944    /// # use etherparse::*;
945    /// #
946    /// let builder = PacketBuilder::
947    ///     ethernet2([1,2,3,4,5,6],
948    ///               [7,8,9,10,11,12])
949    ///    .single_vlan(0x132.try_into().unwrap())
950    ///    .ip(IpHeaders::Ipv6(
951    ///         Ipv6Header{
952    ///             traffic_class: 0,
953    ///             flow_label: 0.try_into().unwrap(),
954    ///             hop_limit: 4,
955    ///             source: [0;16],
956    ///             destination: [0;16],
957    ///             // payload_length & next_header will be replaced during write
958    ///             ..Default::default()
959    ///         },
960    ///         Default::default() // IPv6 extension headers (default is none)
961    ///     ));
962    /// ```
963    pub fn ip(self, ip_header: IpHeaders) -> PacketBuilderStep<IpHeaders> {
964        //use the method from the Ethernet2Header implementation
965        PacketBuilderStep {
966            state: self.state,
967            _marker: marker::PhantomData::<Ethernet2Header> {},
968        }
969        .ip(ip_header)
970    }
971
972    /// Add an IPv6 header
973    ///
974    /// # Example
975    ///
976    /// Basic usage:
977    ///
978    /// ```
979    /// # use etherparse::{PacketBuilder, SingleVlanHeader, VlanHeader};
980    /// #
981    /// let builder = PacketBuilder::
982    ///     ethernet2([1,2,3,4,5,6],     //source mac
983    ///               [7,8,9,10,11,12]) //destination mac
984    ///     .single_vlan(0x123.try_into().unwrap()) // vlan identifier
985    ///     .ipv6(
986    ///         //source
987    ///         [11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
988    ///         //destination
989    ///         [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],
990    ///         //hop_limit
991    ///         47)
992    ///     .udp(21,    //source port
993    ///          1234); //destination port
994    ///
995    /// //payload of the udp packet
996    /// let payload = [1,2,3,4,5,6,7,8];
997    ///
998    /// //get some memory to store the result
999    /// let mut result = Vec::<u8>::with_capacity(
1000    ///                     builder.size(payload.len()));
1001    ///
1002    /// //serialize
1003    /// builder.write(&mut result, &payload).unwrap();
1004    /// ```
1005    pub fn ipv6(
1006        self,
1007        source: [u8; 16],
1008        destination: [u8; 16],
1009        hop_limit: u8,
1010    ) -> PacketBuilderStep<IpHeaders> {
1011        //use the method from the Ethernet2Header implementation
1012        PacketBuilderStep {
1013            state: self.state,
1014            _marker: marker::PhantomData::<Ethernet2Header> {},
1015        }
1016        .ipv6(source, destination, hop_limit)
1017    }
1018
1019    /// Add an IPv4 header
1020    ///
1021    /// # Example
1022    ///
1023    /// Basic usage:
1024    ///
1025    /// ```
1026    /// # use etherparse::{PacketBuilder, SingleVlanHeader, VlanHeader};
1027    /// #
1028    /// let builder = PacketBuilder::
1029    ///     ethernet2([1,2,3,4,5,6],     //source mac
1030    ///               [7,8,9,10,11,12]) //destination mac
1031    ///     .single_vlan(0x123.try_into().unwrap()) // vlan identifier
1032    ///     .ipv4([192,168,1,1], //source ip
1033    ///           [192,168,1,2], //destination ip
1034    ///           20)            //time to life
1035    ///     .udp(21,    //source port
1036    ///          1234); //destination port
1037    ///
1038    /// //payload of the udp packet
1039    /// let payload = [1,2,3,4,5,6,7,8];
1040    ///
1041    /// //get some memory to store the result
1042    /// let mut result = Vec::<u8>::with_capacity(
1043    ///                     builder.size(payload.len()));
1044    ///
1045    /// //serialize
1046    /// builder.write(&mut result, &payload).unwrap();
1047    /// ```
1048    pub fn ipv4(
1049        self,
1050        source: [u8; 4],
1051        destination: [u8; 4],
1052        time_to_live: u8,
1053    ) -> PacketBuilderStep<IpHeaders> {
1054        //use the method from the Ethernet2Header implementation
1055        PacketBuilderStep {
1056            state: self.state,
1057            _marker: marker::PhantomData::<Ethernet2Header> {},
1058        }
1059        .ipv4(source, destination, time_to_live)
1060    }
1061
1062    /// Adds an ARP packet.
1063    ///
1064    /// # Example
1065    ///
1066    /// Basic usage:
1067    ///
1068    /// ```
1069    /// use etherparse::*;
1070    ///
1071    /// let builder = PacketBuilder::
1072    ///     ethernet2([1,2,3,4,5,6],    // source mac
1073    ///               [7,8,9,10,11,12]) // destination mac
1074    ///     .single_vlan(0x123.try_into().unwrap()) // vlan identifier
1075    ///     .arp(ArpPacket::new(
1076    ///         ArpHardwareId::ETHERNET,
1077    ///         EtherType::IPV4,
1078    ///         ArpOperation::REQUEST,
1079    ///         &[1,2,3,4,5,6], // sender_hw_addr
1080    ///         &[7,6,8,9],     // sender_protocol_addr
1081    ///         &[10,11,12,14,15,16], // target_hw_addr
1082    ///         &[17,18,19,20]        // target_protocol_addr
1083    ///     ).unwrap());
1084    ///
1085    /// // get some memory to store the result
1086    /// let mut result = Vec::<u8>::with_capacity(builder.size());
1087    ///
1088    /// // serialize
1089    /// builder.write(&mut result).unwrap();
1090    /// ```
1091    pub fn arp(mut self, arp_packet: ArpPacket) -> PacketBuilderStep<ArpPacket> {
1092        self.state.net_header = Some(NetHeaders::Arp(arp_packet));
1093        //return for next step
1094        PacketBuilderStep {
1095            state: self.state,
1096            _marker: marker::PhantomData::<ArpPacket> {},
1097        }
1098    }
1099}
1100
1101#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1102impl PacketBuilderStep<IpHeaders> {
1103    /// Adds an ICMPv4 header of the given [`Icmpv4Type`] to the packet.
1104    ///
1105    /// If an ICMPv4 header gets added the payload used during the builders `write`
1106    /// call contains the bytes after the header and has different meanings
1107    /// and contents based on the type. Usually all statically sized values
1108    /// known based on the ICMPv4 type & code are part of the header and the
1109    /// payload is used to store contains the dynamic parts of the ICMPv4 packet.
1110    ///
1111    /// Check [`Icmpv4Type`] for a documentation which values are part of the
1112    /// header and what is stored as part of the payload.
1113    ///
1114    /// # Example
1115    ///
1116    /// Basic usage:
1117    ///
1118    /// ```
1119    /// # use etherparse::{PacketBuilder, Icmpv4Type, icmpv4};
1120    /// #
1121    /// let builder = PacketBuilder::
1122    ///    ipv4([192,168,1,1],  //source ip
1123    ///          [192,168,1,2], //destination ip
1124    ///          20)            //time to life
1125    ///    .icmpv4(
1126    ///         Icmpv4Type::TimeExceeded(
1127    ///             icmpv4::TimeExceededCode::TtlExceededInTransit
1128    ///         )
1129    ///     );
1130    ///
1131    /// // what is part of the payload depends on the Icmpv4Type
1132    /// //
1133    /// // In case of `Icmpv4Type::TimeExceeded` the "internet header
1134    /// // + 64 bits of the original data datagram" should be given as
1135    /// // the payload
1136    /// let payload = [1,2,3,4,5,6,7,8];
1137    ///
1138    /// //get some memory to store the result
1139    /// let mut result = Vec::<u8>::with_capacity(
1140    ///                     builder.size(payload.len()));
1141    ///
1142    /// //serialize
1143    /// builder.write(&mut result, &payload).unwrap();
1144    /// ```
1145    pub fn icmpv4(mut self, icmp_type: Icmpv4Type) -> PacketBuilderStep<Icmpv4Header> {
1146        self.state.transport_header = Some(TransportHeader::Icmpv4(Icmpv4Header {
1147            icmp_type,
1148            checksum: 0, // calculated later
1149        }));
1150        //return for next step
1151        PacketBuilderStep {
1152            state: self.state,
1153            _marker: marker::PhantomData::<Icmpv4Header> {},
1154        }
1155    }
1156
1157    /// Adds an ICMPv4 header based on raw numbers.
1158    ///
1159    /// This can be useful when trying to build an ICMPv4 packet
1160    /// which is not fully supported by etherparse and is the equivalent
1161    /// of using [`Icmpv4Type::Unknown`] together with
1162    /// [`PacketBuilderStep<IpHeaders>::icmpv4`].
1163    ///
1164    /// # Example
1165    ///
1166    /// Basic usage:
1167    ///
1168    /// ```
1169    /// # use etherparse::PacketBuilder;
1170    /// #
1171    /// let builder = PacketBuilder::
1172    ///    ipv4([192,168,1,1],  //source ip
1173    ///          [192,168,1,2], //destination ip
1174    ///          20)            //time to life
1175    ///    .icmpv4_raw(
1176    ///         253, // ICMPv4 type (e.g. 253 is RFC3692-style Experiment 1)
1177    ///         0, // ICMPv4 code
1178    ///         [1,2,3,4]  // bytes 5-8 in the ICMPv4 header
1179    ///     );
1180    ///
1181    /// // the payload is written after the 8 byte raw ICMPv4 header
1182    /// let payload = [1,2,3,4,5,6,7,8];
1183    ///
1184    /// // get some memory to store the result
1185    /// let mut result = Vec::<u8>::with_capacity(
1186    ///                     builder.size(payload.len()));
1187    ///
1188    /// // serialize
1189    /// builder.write(&mut result, &payload).unwrap();
1190    /// ```
1191    pub fn icmpv4_raw(
1192        mut self,
1193        type_u8: u8,
1194        code_u8: u8,
1195        bytes5to8: [u8; 4],
1196    ) -> PacketBuilderStep<Icmpv4Header> {
1197        let icmp_type = Icmpv4Type::Unknown {
1198            type_u8,
1199            code_u8,
1200            bytes5to8,
1201        };
1202        self.state.transport_header = Some(TransportHeader::Icmpv4(Icmpv4Header {
1203            icmp_type,
1204            checksum: 0, // calculated later
1205        }));
1206        //return for next step
1207        PacketBuilderStep {
1208            state: self.state,
1209            _marker: marker::PhantomData::<Icmpv4Header> {},
1210        }
1211    }
1212
1213    /// Adds an ICMPv4 echo request packet.
1214    ///
1215    /// # Example
1216    ///
1217    /// Basic usage:
1218    ///
1219    /// ```
1220    /// # use etherparse::PacketBuilder;
1221    /// #
1222    /// let builder = PacketBuilder::
1223    ///    ipv4([192,168,1,1],  //source ip
1224    ///          [192,168,1,2], //destination ip
1225    ///          20)            //time to life
1226    ///    .icmpv4_echo_request(
1227    ///         123, // identifier
1228    ///         456, // sequence number
1229    ///     );
1230    ///
1231    /// // payload of the echo request
1232    /// let payload = [1,2,3,4,5,6,7,8];
1233    ///
1234    /// // get some memory to store the result
1235    /// let mut result = Vec::<u8>::with_capacity(
1236    ///                     builder.size(payload.len()));
1237    ///
1238    /// // serialize
1239    /// builder.write(&mut result, &payload).unwrap();
1240    /// ```
1241    pub fn icmpv4_echo_request(mut self, id: u16, seq: u16) -> PacketBuilderStep<Icmpv4Header> {
1242        let echo_header = IcmpEchoHeader { id, seq };
1243        let icmpv4_echo = Icmpv4Header::new(Icmpv4Type::EchoRequest(echo_header));
1244        self.state.transport_header = Some(TransportHeader::Icmpv4(icmpv4_echo));
1245        //return for next step
1246        PacketBuilderStep {
1247            state: self.state,
1248            _marker: marker::PhantomData::<Icmpv4Header> {},
1249        }
1250    }
1251
1252    /// Adds an ICMPv4 echo reply packet.
1253    ///
1254    /// # Example
1255    ///
1256    /// Basic usage:
1257    ///
1258    /// ```
1259    /// # use etherparse::PacketBuilder;
1260    /// #
1261    /// let builder = PacketBuilder::
1262    ///    ipv4([192,168,1,1],  //source ip
1263    ///          [192,168,1,2], //destination ip
1264    ///          20)            //time to life
1265    ///    .icmpv4_echo_reply(
1266    ///         123, // identifier
1267    ///         456, // sequence number
1268    ///     );
1269    ///
1270    /// // payload of the echo reply
1271    /// let payload = [1,2,3,4,5,6,7,8];
1272    ///
1273    /// // get some memory to store the result
1274    /// let mut result = Vec::<u8>::with_capacity(
1275    ///                     builder.size(payload.len()));
1276    ///
1277    /// // serialize
1278    /// builder.write(&mut result, &payload).unwrap();
1279    /// ```
1280    pub fn icmpv4_echo_reply(mut self, id: u16, seq: u16) -> PacketBuilderStep<Icmpv4Header> {
1281        let echo_header = IcmpEchoHeader { id, seq };
1282        let icmpv4_echo = Icmpv4Header::new(Icmpv4Type::EchoReply(echo_header));
1283        self.state.transport_header = Some(TransportHeader::Icmpv4(icmpv4_echo));
1284        //return for next step
1285        PacketBuilderStep {
1286            state: self.state,
1287            _marker: marker::PhantomData::<Icmpv4Header> {},
1288        }
1289    }
1290
1291    /// Adds an ICMPv6 header of the given [`Icmpv6Type`] to the packet.
1292    ///
1293    /// If an ICMPv6 header gets added the payload used during the builders `write`
1294    /// call contains the bytes after the header and has different meanings
1295    /// and contents based on the type. Usually all statically sized values
1296    /// known based on the ICMPv6 type & code are part of the header and the
1297    /// payload is used to store contains the dynamic parts of the ICMPv6 packet.
1298    ///
1299    /// Check [`Icmpv6Type`] for a documentation which values are part of the
1300    /// header and what is stored as part of the payload.
1301    ///
1302    /// # Example
1303    ///
1304    /// Basic usage:
1305    ///
1306    /// ```
1307    /// # use etherparse::{PacketBuilder, Icmpv6Type, icmpv6};
1308    /// #
1309    /// let builder = PacketBuilder::
1310    ///     ipv6(
1311    ///         //source
1312    ///         [11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
1313    ///         //destination
1314    ///         [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],
1315    ///         //hop_limit
1316    ///         47)
1317    ///    .icmpv6(
1318    ///         Icmpv6Type::TimeExceeded(
1319    ///             icmpv6::TimeExceededCode::HopLimitExceeded
1320    ///         )
1321    ///     );
1322    ///
1323    /// // what is part of the payload depends on the Icmpv6Type
1324    /// //
1325    /// // In case of `Icmpv6Type::TimeExceeded` "As much of invoking packet
1326    /// // as possible without the ICMPv6 packet exceeding the minimum IPv6 MTU"
1327    /// // should be given as the payload.
1328    /// let payload = [1,2,3,4,5,6,7,8];
1329    ///
1330    /// //get some memory to store the result
1331    /// let mut result = Vec::<u8>::with_capacity(
1332    ///                     builder.size(payload.len()));
1333    ///
1334    /// //serialize
1335    /// builder.write(&mut result, &payload).unwrap();
1336    /// ```
1337    pub fn icmpv6(mut self, icmp_type: Icmpv6Type) -> PacketBuilderStep<Icmpv6Header> {
1338        self.state.transport_header = Some(TransportHeader::Icmpv6(Icmpv6Header {
1339            icmp_type,
1340            checksum: 0, // calculated later
1341        }));
1342        //return for next step
1343        PacketBuilderStep {
1344            state: self.state,
1345            _marker: marker::PhantomData::<Icmpv6Header> {},
1346        }
1347    }
1348
1349    /// Adds an ICMPv6 header based on raw values.
1350    ///
1351    /// This can be useful when trying to build an ICMPv6 packet
1352    /// which is not fully supported by etherparse and is the equivalent
1353    /// of using [`Icmpv6Type::Unknown`] together with
1354    /// [`PacketBuilderStep<IpHeaders>::icmpv6`].
1355    ///
1356    /// # Example
1357    ///
1358    /// Basic usage:
1359    ///
1360    /// ```
1361    /// # use etherparse::PacketBuilder;
1362    /// #
1363    /// let builder = PacketBuilder::
1364    ///     ipv6(
1365    ///         //source
1366    ///         [11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
1367    ///         //destination
1368    ///         [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],
1369    ///         //hop_limit
1370    ///         47)
1371    ///    .icmpv4_raw(
1372    ///         200, // ICMPv6 type (e.g. 200 is for "private experimentation")
1373    ///         0, // ICMPv6 code
1374    ///         [1,2,3,4]  // bytes 5-8 in the ICMPv6 header
1375    ///     );
1376    ///
1377    /// // the payload is written after the 8 byte raw ICMPv6 header
1378    /// let payload = [1,2,3,4,5,6,7,8];
1379    ///
1380    /// //get some memory to store the result
1381    /// let mut result = Vec::<u8>::with_capacity(
1382    ///                     builder.size(payload.len()));
1383    ///
1384    /// //serialize
1385    /// builder.write(&mut result, &payload).unwrap();
1386    /// ```
1387    pub fn icmpv6_raw(
1388        mut self,
1389        type_u8: u8,
1390        code_u8: u8,
1391        bytes5to8: [u8; 4],
1392    ) -> PacketBuilderStep<Icmpv6Header> {
1393        let icmp_type = Icmpv6Type::Unknown {
1394            type_u8,
1395            code_u8,
1396            bytes5to8,
1397        };
1398        self.state.transport_header = Some(TransportHeader::Icmpv6(Icmpv6Header {
1399            icmp_type,
1400            checksum: 0, // calculated later
1401        }));
1402        //return for next step
1403        PacketBuilderStep {
1404            state: self.state,
1405            _marker: marker::PhantomData::<Icmpv6Header> {},
1406        }
1407    }
1408
1409    /// Adds an ICMPv6 echo reply packet.
1410    ///
1411    /// # Example
1412    ///
1413    /// Basic usage:
1414    ///
1415    /// ```
1416    /// # use etherparse::PacketBuilder;
1417    /// #
1418    /// let builder = PacketBuilder::
1419    ///     ipv6(
1420    ///         //source
1421    ///         [11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
1422    ///         //destination
1423    ///         [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],
1424    ///         //hop_limit
1425    ///         47)
1426    ///    .icmpv6_echo_request(
1427    ///         123, // identifier
1428    ///         456, // sequence number
1429    ///     );
1430    ///
1431    /// // payload of the echo request
1432    /// let payload = [1,2,3,4,5,6,7,8];
1433    ///
1434    /// //get some memory to store the result
1435    /// let mut result = Vec::<u8>::with_capacity(
1436    ///                     builder.size(payload.len()));
1437    ///
1438    /// //serialize
1439    /// builder.write(&mut result, &payload).unwrap();
1440    /// ```
1441    pub fn icmpv6_echo_request(mut self, id: u16, seq: u16) -> PacketBuilderStep<Icmpv6Header> {
1442        let echo_header = IcmpEchoHeader { id, seq };
1443        let icmpv6_echo = Icmpv6Header::new(Icmpv6Type::EchoRequest(echo_header));
1444        self.state.transport_header = Some(TransportHeader::Icmpv6(icmpv6_echo));
1445        //return for next step
1446        PacketBuilderStep {
1447            state: self.state,
1448            _marker: marker::PhantomData::<Icmpv6Header> {},
1449        }
1450    }
1451
1452    /// Adds an ICMPv6 echo request packet.
1453    ///
1454    /// # Example
1455    ///
1456    /// Basic usage:
1457    ///
1458    /// ```
1459    /// # use etherparse::PacketBuilder;
1460    /// #
1461    /// let builder = PacketBuilder::
1462    ///     ipv6(
1463    ///         //source
1464    ///         [11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
1465    ///         //destination
1466    ///         [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],
1467    ///         //hop_limit
1468    ///         47)
1469    ///    .icmpv6_echo_reply(
1470    ///         123, // identifier
1471    ///         456, // sequence number
1472    ///     );
1473    ///
1474    /// // payload of the echo reply
1475    /// let payload = [1,2,3,4,5,6,7,8];
1476    ///
1477    /// //get some memory to store the result
1478    /// let mut result = Vec::<u8>::with_capacity(
1479    ///                     builder.size(payload.len()));
1480    ///
1481    /// //serialize
1482    /// builder.write(&mut result, &payload).unwrap();
1483    /// ```
1484    pub fn icmpv6_echo_reply(mut self, id: u16, seq: u16) -> PacketBuilderStep<Icmpv6Header> {
1485        let echo_header = IcmpEchoHeader { seq, id };
1486        let icmpv6_echo = Icmpv6Header::new(Icmpv6Type::EchoReply(echo_header));
1487        self.state.transport_header = Some(TransportHeader::Icmpv6(icmpv6_echo));
1488        //return for next step
1489        PacketBuilderStep {
1490            state: self.state,
1491            _marker: marker::PhantomData::<Icmpv6Header> {},
1492        }
1493    }
1494
1495    /// Adds an UDP header.
1496    ///
1497    /// # Example
1498    ///
1499    /// Basic usage:
1500    ///
1501    /// ```
1502    /// # use etherparse::PacketBuilder;
1503    /// #
1504    /// let builder = PacketBuilder::
1505    ///     ethernet2([1,2,3,4,5,6],     //source mac
1506    ///               [7,8,9,10,11,12]) //destination mac
1507    ///    .ipv4([192,168,1,1], //source ip
1508    ///          [192,168,1,2], //destination ip
1509    ///          20)            //time to life
1510    ///    .udp(21,    //source port
1511    ///         1234); //destination port
1512    ///
1513    /// //payload of the udp packet
1514    /// let payload = [1,2,3,4,5,6,7,8];
1515    ///
1516    /// //get some memory to store the result
1517    /// let mut result = Vec::<u8>::with_capacity(
1518    ///                     builder.size(payload.len()));
1519    ///
1520    /// //serialize
1521    /// builder.write(&mut result, &payload).unwrap();
1522    /// ```
1523    pub fn udp(mut self, source_port: u16, destination_port: u16) -> PacketBuilderStep<UdpHeader> {
1524        self.state.transport_header = Some(TransportHeader::Udp(UdpHeader {
1525            source_port,
1526            destination_port,
1527            length: 0,   //calculated later
1528            checksum: 0, //calculated later
1529        }));
1530        //return for next step
1531        PacketBuilderStep {
1532            state: self.state,
1533            _marker: marker::PhantomData::<UdpHeader> {},
1534        }
1535    }
1536
1537    /// Adds a simple TCP header.
1538    ///
1539    /// # Example
1540    ///
1541    /// Basic usage:
1542    ///
1543    /// ```
1544    /// # use etherparse::PacketBuilder;
1545    /// #
1546    /// let builder = PacketBuilder::
1547    ///     ethernet2([1,2,3,4,5,6],     // source mac
1548    ///               [7,8,9,10,11,12]) // destination mac
1549    ///    .ipv4([192,168,1,1], // source ip
1550    ///          [192,168,1,2], // destination ip
1551    ///          20)            // time to life
1552    ///    .tcp(21,    // source port
1553    ///         12,    // destination port
1554    ///         12345, // sequence number
1555    ///         4000); // window size
1556    ///
1557    /// //payload of the udp packet
1558    /// let payload = [1,2,3,4,5,6,7,8];
1559    ///
1560    /// //get some memory to store the result
1561    /// let mut result = Vec::<u8>::with_capacity(
1562    ///                     builder.size(payload.len()));
1563    ///
1564    /// //serialize
1565    /// builder.write(&mut result, &payload).unwrap();
1566    /// ```
1567    pub fn tcp(
1568        mut self,
1569        source_port: u16,
1570        destination_port: u16,
1571        sequence_number: u32,
1572        window_size: u16,
1573    ) -> PacketBuilderStep<TcpHeader> {
1574        self.state.transport_header = Some(TransportHeader::Tcp(TcpHeader::new(
1575            source_port,
1576            destination_port,
1577            sequence_number,
1578            window_size,
1579        )));
1580        //return for next step
1581        PacketBuilderStep {
1582            state: self.state,
1583            _marker: marker::PhantomData::<TcpHeader> {},
1584        }
1585    }
1586
1587    /// Adds a more complicated TCP header.
1588    ///
1589    /// # Example
1590    ///
1591    /// Basic usage:
1592    ///
1593    /// ```
1594    /// # use etherparse::PacketBuilder;
1595    /// use etherparse::TcpHeader;
1596    ///
1597    /// let mut tcp_header = TcpHeader::new(
1598    ///     21,     // source port
1599    ///     12,     // destination port
1600    ///     12345,  // sequence number
1601    ///     4000,   // window size
1602    /// );
1603    /// tcp_header.psh = true;
1604    /// tcp_header.ack = true;
1605    /// tcp_header.acknowledgment_number = 1;
1606    ///
1607    /// let builder = PacketBuilder::
1608    ///     ethernet2([1,2,3,4,5,6],     // source mac
1609    ///               [7,8,9,10,11,12]) // destination mac
1610    ///    .ipv4([192,168,1,1], // source ip
1611    ///          [192,168,1,2], // destination ip
1612    ///          20)            // time to life
1613    ///    .tcp_header(tcp_header);
1614    ///
1615    /// //payload of the udp packet
1616    /// let payload = [1,2,3,4,5,6,7,8];
1617    ///
1618    /// //get some memory to store the result
1619    /// let mut result = Vec::<u8>::with_capacity(
1620    ///                     builder.size(payload.len()));
1621    ///
1622    /// //serialize
1623    /// builder.write(&mut result, &payload).unwrap();
1624    /// ```
1625    pub fn tcp_header(mut self, tcp_header: TcpHeader) -> PacketBuilderStep<TcpHeader> {
1626        self.state.transport_header = Some(TransportHeader::Tcp(tcp_header));
1627        //return for next step
1628        PacketBuilderStep {
1629            state: self.state,
1630            _marker: marker::PhantomData::<TcpHeader> {},
1631        }
1632    }
1633
1634    /// Write all the headers and the payload with the given ip number.
1635    ///
1636    /// `last_next_header_ip_number` will be set in the last extension header
1637    /// or if no extension header exists the ip header as the "next header" or
1638    /// "protocol number".
1639    pub fn write<T: io::Write + Sized>(
1640        mut self,
1641        writer: &mut T,
1642        last_next_header_ip_number: IpNumber,
1643        payload: &[u8],
1644    ) -> Result<(), BuildWriteError> {
1645        match &mut (self.state.net_header) {
1646            Some(NetHeaders::Ipv4(ref mut ip, ref mut exts)) => {
1647                ip.protocol = exts.set_next_headers(last_next_header_ip_number);
1648            }
1649            Some(NetHeaders::Ipv6(ref mut ip, ref mut exts)) => {
1650                ip.next_header = exts.set_next_headers(last_next_header_ip_number);
1651            }
1652            _ => {}
1653        }
1654        final_write_with_net(self, writer, payload)
1655    }
1656
1657    ///Returns the size of the packet when it is serialized
1658    pub fn size(&self, payload_size: usize) -> usize {
1659        final_size(self, payload_size)
1660    }
1661}
1662
1663#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1664impl PacketBuilderStep<Icmpv4Header> {
1665    /// Write all the headers and the payload.
1666    pub fn write<T: io::Write + Sized>(
1667        self,
1668        writer: &mut T,
1669        payload: &[u8],
1670    ) -> Result<(), BuildWriteError> {
1671        final_write_with_net(self, writer, payload)
1672    }
1673
1674    /// Returns the size of the packet when it is serialized
1675    pub fn size(&self, payload_size: usize) -> usize {
1676        final_size(self, payload_size)
1677    }
1678}
1679
1680#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1681impl PacketBuilderStep<Icmpv6Header> {
1682    ///Write all the headers and the payload.
1683    pub fn write<T: io::Write + Sized>(
1684        self,
1685        writer: &mut T,
1686        payload: &[u8],
1687    ) -> Result<(), BuildWriteError> {
1688        final_write_with_net(self, writer, payload)
1689    }
1690
1691    ///Returns the size of the packet when it is serialized
1692    pub fn size(&self, payload_size: usize) -> usize {
1693        final_size(self, payload_size)
1694    }
1695}
1696
1697#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1698impl PacketBuilderStep<UdpHeader> {
1699    ///Write all the headers and the payload.
1700    pub fn write<T: io::Write + Sized>(
1701        self,
1702        writer: &mut T,
1703        payload: &[u8],
1704    ) -> Result<(), BuildWriteError> {
1705        final_write_with_net(self, writer, payload)
1706    }
1707
1708    ///Returns the size of the packet when it is serialized
1709    pub fn size(&self, payload_size: usize) -> usize {
1710        final_size(self, payload_size)
1711    }
1712}
1713
1714#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1715impl PacketBuilderStep<TcpHeader> {
1716    ///Set ns flag (ECN-nonce - concealment protection; experimental: see RFC 3540)
1717    pub fn ns(mut self) -> PacketBuilderStep<TcpHeader> {
1718        self.state
1719            .transport_header
1720            .as_mut()
1721            .unwrap()
1722            .mut_tcp()
1723            .unwrap()
1724            .ns = true;
1725        self
1726    }
1727    ///Set fin flag (No more data from sender)
1728    pub fn fin(mut self) -> PacketBuilderStep<TcpHeader> {
1729        self.state
1730            .transport_header
1731            .as_mut()
1732            .unwrap()
1733            .mut_tcp()
1734            .unwrap()
1735            .fin = true;
1736        self
1737    }
1738    ///Set the syn flag (synchronize sequence numbers)
1739    pub fn syn(mut self) -> PacketBuilderStep<TcpHeader> {
1740        self.state
1741            .transport_header
1742            .as_mut()
1743            .unwrap()
1744            .mut_tcp()
1745            .unwrap()
1746            .syn = true;
1747        self
1748    }
1749    ///Sets the rst flag (reset the connection)
1750    pub fn rst(mut self) -> PacketBuilderStep<TcpHeader> {
1751        self.state
1752            .transport_header
1753            .as_mut()
1754            .unwrap()
1755            .mut_tcp()
1756            .unwrap()
1757            .rst = true;
1758        self
1759    }
1760    ///Sets the psh flag (push function)
1761    pub fn psh(mut self) -> PacketBuilderStep<TcpHeader> {
1762        self.state
1763            .transport_header
1764            .as_mut()
1765            .unwrap()
1766            .mut_tcp()
1767            .unwrap()
1768            .psh = true;
1769        self
1770    }
1771    ///Sets the ack flag and the acknowledgment_number.
1772    pub fn ack(mut self, acknowledgment_number: u32) -> PacketBuilderStep<TcpHeader> {
1773        {
1774            let header = self
1775                .state
1776                .transport_header
1777                .as_mut()
1778                .unwrap()
1779                .mut_tcp()
1780                .unwrap();
1781            header.ack = true;
1782            header.acknowledgment_number = acknowledgment_number;
1783        }
1784        self
1785    }
1786    ///Set the urg flag & the urgent pointer field.
1787    ///
1788    ///The urgent pointer points to the sequence number of the octet following
1789    ///the urgent data.
1790    pub fn urg(mut self, urgent_pointer: u16) -> PacketBuilderStep<TcpHeader> {
1791        {
1792            let header = self
1793                .state
1794                .transport_header
1795                .as_mut()
1796                .unwrap()
1797                .mut_tcp()
1798                .unwrap();
1799            header.urg = true;
1800            header.urgent_pointer = urgent_pointer;
1801        }
1802        self
1803    }
1804    ///Sets ece flag (ECN-Echo, RFC 3168)
1805    pub fn ece(mut self) -> PacketBuilderStep<TcpHeader> {
1806        self.state
1807            .transport_header
1808            .as_mut()
1809            .unwrap()
1810            .mut_tcp()
1811            .unwrap()
1812            .ece = true;
1813        self
1814    }
1815
1816    ///Set cwr flag (Congestion Window Reduced)
1817    ///
1818    ///This flag is set by the sending host to indicate that it received a TCP segment with the ECE flag set and had responded in congestion control mechanism (added to header by RFC 3168).
1819    pub fn cwr(mut self) -> PacketBuilderStep<TcpHeader> {
1820        self.state
1821            .transport_header
1822            .as_mut()
1823            .unwrap()
1824            .mut_tcp()
1825            .unwrap()
1826            .cwr = true;
1827        self
1828    }
1829
1830    ///Set the tcp options of the header.
1831    pub fn options(
1832        mut self,
1833        options: &[TcpOptionElement],
1834    ) -> Result<PacketBuilderStep<TcpHeader>, TcpOptionWriteError> {
1835        self.state
1836            .transport_header
1837            .as_mut()
1838            .unwrap()
1839            .mut_tcp()
1840            .unwrap()
1841            .set_options(options)?;
1842        Ok(self)
1843    }
1844
1845    ///Set the tcp options of the header (setting the bytes directly).
1846    pub fn options_raw(
1847        mut self,
1848        options: &[u8],
1849    ) -> Result<PacketBuilderStep<TcpHeader>, TcpOptionWriteError> {
1850        self.state
1851            .transport_header
1852            .as_mut()
1853            .unwrap()
1854            .mut_tcp()
1855            .unwrap()
1856            .set_options_raw(options)?;
1857        Ok(self)
1858    }
1859
1860    ///Write all the headers and the payload.
1861    pub fn write<T: io::Write + Sized>(
1862        self,
1863        writer: &mut T,
1864        payload: &[u8],
1865    ) -> Result<(), BuildWriteError> {
1866        final_write_with_net(self, writer, payload)
1867    }
1868
1869    ///Returns the size of the packet when it is serialized
1870    pub fn size(&self, payload_size: usize) -> usize {
1871        final_size(self, payload_size)
1872    }
1873}
1874
1875#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1876impl PacketBuilderStep<ArpPacket> {
1877    pub fn write<T: io::Write + Sized>(self, writer: &mut T) -> Result<(), BuildWriteError> {
1878        final_write_with_net(self, writer, &[])?;
1879        Ok(())
1880    }
1881
1882    pub fn size(&self) -> usize {
1883        final_size(self, 0)
1884    }
1885}
1886
1887/// Write all the headers and the payload.
1888fn final_write_with_net<T: io::Write + Sized, B>(
1889    builder: PacketBuilderStep<B>,
1890    writer: &mut T,
1891    payload: &[u8],
1892) -> Result<(), BuildWriteError> {
1893    use BuildWriteError::*;
1894    use NetHeaders::*;
1895
1896    // unpack builder (makes things easier with the borrow checker)
1897    let link = builder.state.link_header;
1898    let vlan = builder.state.vlan_header;
1899    let net = builder.state.net_header;
1900    let mut transport = builder.state.transport_header;
1901
1902    // determine
1903    let net_ether_type = match &net {
1904        Some(Ipv4(_, _)) => ether_type::IPV4,
1905        Some(Ipv6(_, _)) => ether_type::IPV6,
1906        Some(Arp(_)) => ether_type::ARP,
1907        None => unreachable!(),
1908    };
1909
1910    // link header
1911    if let Some(link) = link {
1912        match link {
1913            LinkHeader::Ethernet2(mut eth) => {
1914                eth.ether_type = {
1915                    use crate::VlanHeader::*;
1916                    //determine the ether type depending on if there is a vlan tagging header
1917                    match &vlan {
1918                        Some(Single(_)) => ether_type::VLAN_TAGGED_FRAME,
1919                        Some(Double(_)) => ether_type::PROVIDER_BRIDGING,
1920                        //if no vlan header exists, the id is purely defined by the ip type
1921                        None => net_ether_type,
1922                    }
1923                };
1924                eth.write(writer).map_err(Io)?;
1925            }
1926            LinkHeader::LinuxSll(mut linux_sll) => {
1927                // Assumes that next layers are ether based. If more types of
1928                // layers are supported, this should be updated
1929                debug_assert_eq!(linux_sll.arp_hrd_type, ArpHardwareId::ETHERNET);
1930
1931                linux_sll.protocol_type.change_value(net_ether_type.into());
1932                linux_sll.write(writer).map_err(Io)?;
1933            }
1934        }
1935    }
1936
1937    // write the vlan header if it exists
1938    use crate::VlanHeader::*;
1939    match vlan {
1940        Some(Single(mut value)) => {
1941            //set ether types
1942            value.ether_type = net_ether_type;
1943            //serialize
1944            value.write(writer).map_err(Io)?;
1945        }
1946        Some(Double(mut value)) => {
1947            //set ether types
1948            value.outer.ether_type = ether_type::VLAN_TAGGED_FRAME;
1949            value.inner.ether_type = net_ether_type;
1950            //serialize
1951            value.outer.write(writer).map_err(Io)?;
1952            value.inner.write(writer).map_err(Io)?;
1953        }
1954        None => {}
1955    }
1956
1957    // set transport header length (needs to be done here
1958    // so following steps can correctly calculate the checksum)
1959    use TransportHeader::*;
1960    match &mut transport {
1961        Some(Udp(ref mut udp)) => {
1962            udp.length = (UdpHeader::LEN + payload.len()) as u16;
1963        }
1964        Some(Tcp(_)) => {}
1965        Some(Icmpv4(_)) => {}
1966        Some(Icmpv6(_)) => {}
1967        None => {}
1968    }
1969
1970    // net header
1971    match net {
1972        Some(NetHeaders::Ipv4(mut ip, mut ip_exts)) => {
1973            // set payload length & ip number
1974            ip.set_payload_len(
1975                ip_exts.header_len()
1976                    + transport.as_ref().map(|v| v.header_len()).unwrap_or(0)
1977                    + payload.len(),
1978            )
1979            .map_err(PayloadLen)?;
1980
1981            if let Some(transport) = &transport {
1982                ip.protocol = ip_exts.set_next_headers(match &transport {
1983                    Icmpv4(_) => ip_number::ICMP,
1984                    Icmpv6(_) => ip_number::IPV6_ICMP,
1985                    Udp(_) => ip_number::UDP,
1986                    Tcp(_) => ip_number::TCP,
1987                });
1988            }
1989
1990            // write ip header & extensions
1991            ip.write(writer).map_err(Io)?;
1992            ip_exts.write(writer, ip.protocol).map_err(|err| {
1993                use err::ipv4_exts::HeaderWriteError as I;
1994                match err {
1995                    I::Io(err) => Io(err),
1996                    I::Content(err) => Ipv4Exts(err),
1997                }
1998            })?;
1999
2000            // update the transport layer checksum
2001            if let Some(t) = &mut transport {
2002                t.update_checksum_ipv4(&ip, payload).map_err(|err| {
2003                    use err::packet::TransportChecksumError as I;
2004                    match err {
2005                        I::PayloadLen(err) => PayloadLen(err),
2006                        I::Icmpv6InIpv4 => Icmpv6InIpv4,
2007                    }
2008                })?;
2009            }
2010        }
2011        Some(NetHeaders::Ipv6(mut ip, mut ip_exts)) => {
2012            // set payload length & ip number
2013            ip.set_payload_length(
2014                ip_exts.header_len()
2015                    + transport.as_ref().map(|v| v.header_len()).unwrap_or(0)
2016                    + payload.len(),
2017            )
2018            .map_err(PayloadLen)?;
2019
2020            if let Some(transport) = &transport {
2021                ip.next_header = ip_exts.set_next_headers(match &transport {
2022                    Icmpv4(_) => ip_number::ICMP,
2023                    Icmpv6(_) => ip_number::IPV6_ICMP,
2024                    Udp(_) => ip_number::UDP,
2025                    Tcp(_) => ip_number::TCP,
2026                });
2027            }
2028
2029            // write ip header & extensions
2030            ip.write(writer).map_err(Io)?;
2031            ip_exts.write(writer, ip.next_header).map_err(|err| {
2032                use err::ipv6_exts::HeaderWriteError as I;
2033                match err {
2034                    I::Io(err) => Io(err),
2035                    I::Content(err) => Ipv6Exts(err),
2036                }
2037            })?;
2038
2039            // update the transport layer checksum
2040            if let Some(t) = &mut transport {
2041                t.update_checksum_ipv6(&ip, payload).map_err(PayloadLen)?;
2042            }
2043        }
2044        Some(NetHeaders::Arp(arp)) => {
2045            writer.write_all(&arp.to_bytes()).map_err(Io)?;
2046        }
2047        None => {}
2048    }
2049
2050    // write transport header
2051    if let Some(transport) = transport {
2052        transport.write(writer).map_err(Io)?;
2053    }
2054
2055    // and finally the payload
2056    writer.write_all(payload).map_err(Io)?;
2057
2058    Ok(())
2059}
2060
2061///Returns the size of the packet when it is serialized
2062fn final_size<B>(builder: &PacketBuilderStep<B>, payload_size: usize) -> usize {
2063    use crate::NetHeaders::*;
2064    use crate::TransportHeader::*;
2065    use crate::VlanHeader::*;
2066    (match builder.state.link_header {
2067        Some(ref header) => header.header_len(),
2068        None => 0,
2069    }) + match builder.state.vlan_header {
2070        Some(Single(_)) => SingleVlanHeader::LEN,
2071        Some(Double(_)) => SingleVlanHeader::LEN * 2,
2072        None => 0,
2073    } + match builder.state.net_header {
2074        Some(Ipv4(ref value, ref ext)) => value.header_len() + ext.header_len(),
2075        Some(Ipv6(_, ref ext)) => Ipv6Header::LEN + ext.header_len(),
2076        Some(Arp(ref packet)) => packet.packet_len(),
2077        None => 0,
2078    } + match builder.state.transport_header {
2079        Some(Icmpv4(ref value)) => value.header_len(),
2080        Some(Icmpv6(ref value)) => value.header_len(),
2081        Some(Udp(_)) => UdpHeader::LEN,
2082        Some(Tcp(ref value)) => value.header_len(),
2083        None => 0,
2084    } + payload_size
2085}
2086
2087#[cfg(test)]
2088mod white_box_tests {
2089    use super::*;
2090    use alloc::vec::Vec;
2091
2092    //white box tests that need internal access
2093    #[test]
2094    fn size() {
2095        assert_eq!(
2096            0,
2097            PacketBuilderStep::<UdpHeader> {
2098                state: PacketImpl {
2099                    link_header: None,
2100                    net_header: None,
2101                    vlan_header: None,
2102                    transport_header: None,
2103                },
2104                _marker: marker::PhantomData::<UdpHeader> {}
2105            }
2106            .size(0)
2107        );
2108    }
2109
2110    #[test]
2111    #[should_panic]
2112    fn final_write_panic_missing_ip() {
2113        let mut writer = Vec::new();
2114        final_write_with_net(
2115            PacketBuilderStep::<UdpHeader> {
2116                state: PacketImpl {
2117                    link_header: None,
2118                    net_header: None,
2119                    vlan_header: None,
2120                    transport_header: None,
2121                },
2122                _marker: marker::PhantomData::<UdpHeader> {},
2123            },
2124            &mut writer,
2125            &[],
2126        )
2127        .unwrap();
2128    }
2129}
2130
2131#[cfg(test)]
2132mod test {
2133    use super::*;
2134    use crate::test_gens::*;
2135    use alloc::{vec, vec::Vec};
2136    use proptest::prelude::*;
2137    use std::io::Read;
2138
2139    #[test]
2140    fn eth_arp() {
2141        let expected_header = ArpPacket::new(
2142            ArpHardwareId::ETHERNET,
2143            EtherType::IPV4,
2144            ArpOperation::REQUEST,
2145            &[20, 30, 40, 50, 60, 70],
2146            &[10, 1, 1, 5],
2147            &[00, 01, 02, 03, 04, 05],
2148            &[192, 168, 1, 2],
2149        )
2150        .unwrap();
2151
2152        let mut serialized = Vec::new();
2153
2154        let pkg = PacketBuilder::ethernet2(
2155            [0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
2156            [0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
2157        )
2158        .arp(expected_header.clone());
2159
2160        let target_size = pkg.size();
2161        pkg.write(&mut serialized).unwrap();
2162
2163        // validate that the predicted size was matching
2164        assert_eq!(serialized.len(), target_size);
2165
2166        // deserialize each part of the message and check it
2167        use std::io::Cursor;
2168        let mut cursor = Cursor::new(&serialized);
2169
2170        // ethernet 2 header
2171        assert_eq!(
2172            Ethernet2Header::read(&mut cursor).unwrap(),
2173            Ethernet2Header {
2174                source: [0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
2175                destination: [0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
2176                ether_type: ether_type::ARP
2177            }
2178        );
2179
2180        // arp packet
2181        assert_eq!(ArpPacket::read(&mut cursor).unwrap(), expected_header);
2182    }
2183
2184    #[test]
2185    fn eth_vlan_arp() {
2186        let expected_arp = ArpPacket::new(
2187            ArpHardwareId::ETHERNET,
2188            EtherType::IPV4,
2189            ArpOperation::REQUEST,
2190            &[20, 30, 40, 50, 60, 70],
2191            &[10, 1, 1, 5],
2192            &[00, 01, 02, 03, 04, 05],
2193            &[192, 168, 1, 2],
2194        )
2195        .unwrap();
2196        let vlan = SingleVlanHeader {
2197            pcp: VlanPcp::ZERO,
2198            drop_eligible_indicator: false,
2199            vlan_id: VlanId::try_new(123).unwrap(),
2200            ether_type: EtherType(0), // should get overwritten
2201        };
2202
2203        let mut serialized = Vec::new();
2204
2205        let pkg = PacketBuilder::ethernet2(
2206            [0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
2207            [0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
2208        )
2209        .vlan(VlanHeader::Single(vlan.clone()))
2210        .arp(expected_arp.clone());
2211
2212        let target_size = pkg.size();
2213        pkg.write(&mut serialized).unwrap();
2214
2215        // validate that the predicted size was matching
2216        assert_eq!(serialized.len(), target_size);
2217
2218        // deserialize each part of the message and check it
2219        use std::io::Cursor;
2220        let mut cursor = Cursor::new(&serialized);
2221
2222        // ethernet 2 header
2223        assert_eq!(
2224            Ethernet2Header::read(&mut cursor).unwrap(),
2225            Ethernet2Header {
2226                source: [0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
2227                destination: [0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
2228                ether_type: ether_type::VLAN_TAGGED_FRAME
2229            }
2230        );
2231
2232        // vlan header
2233        let mut expected_vlan = vlan.clone();
2234        expected_vlan.ether_type = EtherType::ARP;
2235        assert_eq!(SingleVlanHeader::read(&mut cursor).unwrap(), expected_vlan);
2236
2237        // arp packet
2238        assert_eq!(ArpPacket::read(&mut cursor).unwrap(), expected_arp);
2239    }
2240
2241    #[test]
2242    fn eth_ipv4_udp() {
2243        //generate
2244        let in_payload = [24, 25, 26, 27];
2245        let mut serialized = Vec::new();
2246        PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
2247            .ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
2248            .udp(22, 23)
2249            .write(&mut serialized, &in_payload)
2250            .unwrap();
2251
2252        //check the deserialized size
2253        let expected_ip_size: usize = UdpHeader::LEN + in_payload.len();
2254        assert_eq!(
2255            expected_ip_size + Ethernet2Header::LEN + Ipv4Header::MIN_LEN,
2256            serialized.len()
2257        );
2258
2259        //deserialize and check that everything is as expected
2260        use std::io::Cursor;
2261        //deserialize each part of the message and check it
2262        let mut cursor = Cursor::new(&serialized);
2263
2264        //ethernet 2 header
2265        assert_eq!(
2266            Ethernet2Header::read(&mut cursor).unwrap(),
2267            Ethernet2Header {
2268                source: [1, 2, 3, 4, 5, 6],
2269                destination: [7, 8, 9, 10, 11, 12],
2270                ether_type: ether_type::IPV4
2271            }
2272        );
2273
2274        //ip header
2275        let ip_actual = Ipv4Header::read(&mut cursor).unwrap();
2276        let mut ip_expected = Ipv4Header::new(
2277            expected_ip_size as u16,
2278            21, //ttl
2279            ip_number::UDP,
2280            [13, 14, 15, 16],
2281            [17, 18, 19, 20],
2282        )
2283        .unwrap();
2284        ip_expected.header_checksum = ip_expected.calc_header_checksum();
2285        assert_eq!(ip_actual, ip_expected);
2286
2287        //udp header
2288        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
2289        let udp_expected =
2290            UdpHeader::with_ipv4_checksum(22, 23, &ip_expected, &in_payload).unwrap();
2291        assert_eq!(udp_actual, udp_expected);
2292
2293        //payload
2294        let mut actual_payload: [u8; 4] = [0; 4];
2295        cursor.read_exact(&mut actual_payload).unwrap();
2296        assert_eq!(actual_payload, in_payload);
2297    }
2298
2299    #[test]
2300    fn linuxsll_ipv4_udp() {
2301        //generate
2302        let in_payload = [24, 25, 26, 27];
2303        let mut serialized = Vec::new();
2304        PacketBuilder::linux_sll(LinuxSllPacketType::OUTGOING, 6, [7, 8, 9, 10, 11, 12, 0, 0])
2305            .ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
2306            .udp(22, 23)
2307            .write(&mut serialized, &in_payload)
2308            .unwrap();
2309
2310        //check the deserialized size
2311        let expected_ip_size: usize = UdpHeader::LEN + in_payload.len();
2312        assert_eq!(
2313            expected_ip_size + LinuxSllHeader::LEN + Ipv4Header::MIN_LEN,
2314            serialized.len()
2315        );
2316
2317        //deserialize and check that everything is as expected
2318        use std::io::Cursor;
2319        //deserialize each part of the message and check it
2320        let mut cursor = Cursor::new(&serialized);
2321
2322        //ethernet 2 header
2323        assert_eq!(
2324            LinuxSllHeader::read(&mut cursor).unwrap(),
2325            LinuxSllHeader {
2326                packet_type: LinuxSllPacketType::OUTGOING,
2327                arp_hrd_type: ArpHardwareId::ETHERNET,
2328                sender_address_valid_length: 6,
2329                sender_address: [7, 8, 9, 10, 11, 12, 0, 0],
2330                protocol_type: LinuxSllProtocolType::EtherType(EtherType::IPV4)
2331            }
2332        );
2333
2334        //ip header
2335        let ip_actual = Ipv4Header::read(&mut cursor).unwrap();
2336        let mut ip_expected = Ipv4Header::new(
2337            expected_ip_size as u16,
2338            21, //ttl
2339            ip_number::UDP,
2340            [13, 14, 15, 16],
2341            [17, 18, 19, 20],
2342        )
2343        .unwrap();
2344        ip_expected.header_checksum = ip_expected.calc_header_checksum();
2345        assert_eq!(ip_actual, ip_expected);
2346
2347        //udp header
2348        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
2349        let udp_expected =
2350            UdpHeader::with_ipv4_checksum(22, 23, &ip_expected, &in_payload).unwrap();
2351        assert_eq!(udp_actual, udp_expected);
2352
2353        //payload
2354        let mut actual_payload: [u8; 4] = [0; 4];
2355        cursor.read_exact(&mut actual_payload).unwrap();
2356        assert_eq!(actual_payload, in_payload);
2357    }
2358
2359    #[test]
2360    fn linuxsll_arp() {
2361        let expected_arp = ArpPacket::new(
2362            ArpHardwareId::ETHERNET,
2363            EtherType::IPV4,
2364            ArpOperation::REQUEST,
2365            &[20, 30, 40, 50, 60, 70],
2366            &[10, 1, 1, 5],
2367            &[00, 01, 02, 03, 04, 05],
2368            &[192, 168, 1, 2],
2369        )
2370        .unwrap();
2371
2372        // build packet
2373        let builder =
2374            PacketBuilder::linux_sll(LinuxSllPacketType::OUTGOING, 6, [7, 8, 9, 10, 11, 12, 0, 0])
2375                .arp(expected_arp.clone());
2376
2377        let predicted_size = builder.size();
2378
2379        let mut serialized = Vec::with_capacity(builder.size());
2380        builder.write(&mut serialized).unwrap();
2381
2382        // validate predicted size
2383        assert_eq!(predicted_size, serialized.len());
2384
2385        // deserialize each part of the message and check it
2386        use std::io::Cursor;
2387        let mut cursor = Cursor::new(&serialized);
2388
2389        // linux sll header
2390        assert_eq!(
2391            LinuxSllHeader::read(&mut cursor).unwrap(),
2392            LinuxSllHeader {
2393                packet_type: LinuxSllPacketType::OUTGOING,
2394                arp_hrd_type: ArpHardwareId::ETHERNET,
2395                sender_address_valid_length: 6,
2396                sender_address: [7, 8, 9, 10, 11, 12, 0, 0],
2397                protocol_type: LinuxSllProtocolType::EtherType(EtherType::ARP)
2398            }
2399        );
2400
2401        // arp
2402        assert_eq!(ArpPacket::read(&mut cursor).unwrap(), expected_arp);
2403    }
2404
2405    #[test]
2406    fn ipv4() {
2407        let auth_ext = IpAuthHeader::new(0.into(), 1, 2, &[3, 4, 5, 6]).unwrap();
2408
2409        //generate
2410        let in_payload = [22, 23, 24, 25];
2411        let mut serialized = Vec::new();
2412        let builder = PacketBuilder::ip(IpHeaders::Ipv4(
2413            Ipv4Header::new(
2414                in_payload.len() as u16,
2415                21,
2416                0.into(),
2417                [13, 14, 15, 16],
2418                [17, 18, 19, 20],
2419            )
2420            .unwrap(),
2421            Ipv4Extensions {
2422                auth: Some(auth_ext.clone()),
2423            },
2424        ));
2425
2426        // check size
2427        assert_eq!(
2428            builder.size(in_payload.len()),
2429            Ipv4Header::MIN_LEN + auth_ext.header_len() + in_payload.len()
2430        );
2431
2432        // write
2433        serialized.reserve(builder.size(in_payload.len()));
2434        builder
2435            .write(&mut serialized, 200.into(), &in_payload)
2436            .unwrap();
2437
2438        //check the deserialized size
2439        assert_eq!(
2440            Ipv4Header::MIN_LEN + auth_ext.header_len() + in_payload.len(),
2441            serialized.len()
2442        );
2443
2444        //deserialize and check that everything is as expected
2445        use std::io::{Cursor, Read};
2446
2447        //deserialize each part of the message and check it
2448        let mut cursor = Cursor::new(&serialized);
2449
2450        //ip header
2451        let ip_actual = Ipv4Header::read(&mut cursor).unwrap();
2452        let mut ip_expected = Ipv4Header::new(
2453            (auth_ext.header_len() + in_payload.len()) as u16,
2454            21,              //ttl
2455            ip_number::AUTH, // should have been set
2456            [13, 14, 15, 16],
2457            [17, 18, 19, 20],
2458        )
2459        .unwrap();
2460        ip_expected.header_checksum = ip_expected.calc_header_checksum();
2461        assert_eq!(ip_actual, ip_expected);
2462
2463        // auth header
2464        let auth_actual = IpAuthHeader::read(&mut cursor).unwrap();
2465        assert_eq!(
2466            auth_actual,
2467            IpAuthHeader::new(
2468                200.into(), // ip number should have been set
2469                1,
2470                2,
2471                &[3, 4, 5, 6]
2472            )
2473            .unwrap()
2474        );
2475
2476        //payload
2477        let mut actual_payload: [u8; 4] = [0; 4];
2478        cursor.read_exact(&mut actual_payload).unwrap();
2479        assert_eq!(actual_payload, in_payload);
2480    }
2481
2482    #[test]
2483    fn ipv6() {
2484        let auth_ext = IpAuthHeader::new(0.into(), 1, 2, &[3, 4, 5, 6]).unwrap();
2485
2486        //generate
2487        let in_payload = [48, 49, 50, 51];
2488        let mut serialized = Vec::new();
2489        let builder = PacketBuilder::ip(IpHeaders::Ipv6(
2490            Ipv6Header {
2491                traffic_class: 0,
2492                flow_label: Ipv6FlowLabel::ZERO,
2493                payload_length: in_payload.len() as u16,
2494                next_header: 0.into(),
2495                hop_limit: 47,
2496                source: [
2497                    11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
2498                ],
2499                destination: [
2500                    31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
2501                ],
2502            },
2503            Ipv6Extensions {
2504                hop_by_hop_options: None,
2505                destination_options: None,
2506                routing: None,
2507                fragment: None,
2508                auth: Some(auth_ext.clone()),
2509            },
2510        ));
2511
2512        // check size
2513        assert_eq!(
2514            builder.size(in_payload.len()),
2515            Ipv6Header::LEN + auth_ext.header_len() + in_payload.len()
2516        );
2517
2518        // write
2519        builder
2520            .write(&mut serialized, 200.into(), &in_payload)
2521            .unwrap();
2522
2523        //check the deserialized size
2524        assert_eq!(
2525            Ipv6Header::LEN + auth_ext.header_len() + in_payload.len(),
2526            serialized.len()
2527        );
2528
2529        //deserialize and check that everything is as expected
2530        use std::io::{Cursor, Read};
2531
2532        //deserialize each part of the message and check it
2533        let mut cursor = Cursor::new(&serialized);
2534
2535        //ip header
2536        let ip_actual = Ipv6Header::read(&mut cursor).unwrap();
2537        let ip_expected = Ipv6Header {
2538            traffic_class: 0,
2539            flow_label: Ipv6FlowLabel::ZERO,
2540            payload_length: (auth_ext.header_len() + in_payload.len()) as u16,
2541            next_header: ip_number::AUTH, // should have been set
2542            hop_limit: 47,
2543            source: [
2544                11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
2545            ],
2546            destination: [
2547                31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
2548            ],
2549        };
2550
2551        assert_eq!(ip_actual, ip_expected);
2552
2553        // auth header
2554        let auth_actual = IpAuthHeader::read(&mut cursor).unwrap();
2555        assert_eq!(
2556            auth_actual,
2557            IpAuthHeader::new(
2558                200.into(), // ip number should have been set
2559                1,
2560                2,
2561                &[3, 4, 5, 6]
2562            )
2563            .unwrap()
2564        );
2565
2566        //payload
2567        let mut actual_payload: [u8; 4] = [0; 4];
2568        cursor.read_exact(&mut actual_payload).unwrap();
2569        assert_eq!(actual_payload, in_payload);
2570    }
2571
2572    #[test]
2573    fn ipv4_udp() {
2574        //generate
2575        let in_payload = [24, 25, 26, 27];
2576        let mut serialized = Vec::new();
2577        PacketBuilder::ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
2578            .udp(22, 23)
2579            .write(&mut serialized, &in_payload)
2580            .unwrap();
2581
2582        //check the deserialized size
2583        let expected_ip_size: usize = UdpHeader::LEN + in_payload.len();
2584        assert_eq!(expected_ip_size + Ipv4Header::MIN_LEN, serialized.len());
2585
2586        //deserialize and check that everything is as expected
2587        use std::io::{Cursor, Read};
2588
2589        //deserialize each part of the message and check it
2590        let mut cursor = Cursor::new(&serialized);
2591
2592        //ip header
2593        let ip_actual = Ipv4Header::read(&mut cursor).unwrap();
2594        let mut ip_expected = Ipv4Header::new(
2595            expected_ip_size as u16,
2596            21, //ttl
2597            ip_number::UDP,
2598            [13, 14, 15, 16],
2599            [17, 18, 19, 20],
2600        )
2601        .unwrap();
2602        ip_expected.header_checksum = ip_expected.calc_header_checksum();
2603        assert_eq!(ip_actual, ip_expected);
2604
2605        //udp header
2606        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
2607        let udp_expected =
2608            UdpHeader::with_ipv4_checksum(22, 23, &ip_expected, &in_payload).unwrap();
2609        assert_eq!(udp_actual, udp_expected);
2610
2611        //payload
2612        let mut actual_payload: [u8; 4] = [0; 4];
2613        cursor.read_exact(&mut actual_payload).unwrap();
2614        assert_eq!(actual_payload, in_payload);
2615    }
2616
2617    #[test]
2618    fn ipv6_udp() {
2619        //generate
2620        let in_payload = [24, 25, 26, 27];
2621        let mut serialized = Vec::new();
2622        PacketBuilder::ipv6(
2623            //source
2624            [
2625                11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
2626            ],
2627            //destination
2628            [
2629                31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
2630            ],
2631            //hop_limit
2632            47,
2633        )
2634        .udp(22, 23)
2635        .write(&mut serialized, &in_payload)
2636        .unwrap();
2637
2638        //check the deserialized size
2639        let expected_ip_size: usize = UdpHeader::LEN + in_payload.len();
2640        assert_eq!(expected_ip_size + Ipv6Header::LEN, serialized.len());
2641
2642        //deserialize and check that everything is as expected
2643        use std::io::{Cursor, Read};
2644
2645        //deserialize each part of the message and check it
2646        let mut cursor = Cursor::new(&serialized);
2647
2648        //ip header
2649        let ip_actual = Ipv6Header::read(&mut cursor).unwrap();
2650        let ip_expected = Ipv6Header {
2651            traffic_class: 0,
2652            flow_label: Ipv6FlowLabel::ZERO,
2653            payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
2654            next_header: ip_number::UDP,
2655            hop_limit: 47,
2656            source: [
2657                11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
2658            ],
2659            destination: [
2660                31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
2661            ],
2662        };
2663
2664        assert_eq!(ip_actual, ip_expected);
2665
2666        //udp header
2667        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
2668        let udp_expected =
2669            UdpHeader::with_ipv6_checksum(22, 23, &ip_expected, &in_payload).unwrap();
2670        assert_eq!(udp_actual, udp_expected);
2671
2672        //payload
2673        let mut actual_payload: [u8; 4] = [0; 4];
2674        cursor.read_exact(&mut actual_payload).unwrap();
2675        assert_eq!(actual_payload, in_payload);
2676    }
2677
2678    #[test]
2679    fn ipv4_custom_udp() {
2680        //generate
2681        let in_payload = [24, 25, 26, 27];
2682        let mut serialized = Vec::new();
2683        PacketBuilder::ip(IpHeaders::Ipv4(
2684            Ipv4Header::new(
2685                0,                //payload_len will be replaced during write
2686                12,               //time_to_live
2687                ip_number::TCP,   //will be replaced during write
2688                [13, 14, 15, 16], //source
2689                [17, 18, 19, 20], //destination
2690            )
2691            .unwrap(),
2692            Default::default(),
2693        ))
2694        .udp(22, 23)
2695        .write(&mut serialized, &in_payload)
2696        .unwrap();
2697
2698        //check the deserialized size
2699        let expected_ip_size: usize = UdpHeader::LEN + in_payload.len();
2700        assert_eq!(expected_ip_size + Ipv4Header::MIN_LEN, serialized.len());
2701
2702        //deserialize and check that everything is as expected
2703        use std::io::{Cursor, Read};
2704
2705        //deserialize each part of the message and check it
2706        let mut cursor = Cursor::new(&serialized);
2707
2708        //ip header
2709        let ip_actual = Ipv4Header::read(&mut cursor).unwrap();
2710        let mut ip_expected = Ipv4Header::new(
2711            expected_ip_size as u16,
2712            12, //ttl
2713            ip_number::UDP,
2714            [13, 14, 15, 16],
2715            [17, 18, 19, 20],
2716        )
2717        .unwrap();
2718        ip_expected.header_checksum = ip_expected.calc_header_checksum();
2719        assert_eq!(ip_actual, ip_expected);
2720
2721        //udp header
2722        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
2723        let udp_expected =
2724            UdpHeader::with_ipv4_checksum(22, 23, &ip_expected, &in_payload).unwrap();
2725        assert_eq!(udp_actual, udp_expected);
2726
2727        //payload
2728        let mut actual_payload: [u8; 4] = [0; 4];
2729        cursor.read_exact(&mut actual_payload).unwrap();
2730        assert_eq!(actual_payload, in_payload);
2731    }
2732
2733    #[test]
2734    fn eth_ipv6_udp() {
2735        //generate
2736        let in_payload = [50, 51, 52, 53];
2737        let mut serialized = Vec::new();
2738        PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
2739            .ipv6(
2740                [
2741                    11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
2742                ],
2743                [
2744                    31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
2745                ],
2746                47,
2747            )
2748            .udp(48, 49)
2749            .write(&mut serialized, &in_payload)
2750            .unwrap();
2751
2752        //check the deserialized size
2753        assert_eq!(
2754            Ethernet2Header::LEN + Ipv6Header::LEN + UdpHeader::LEN + in_payload.len(),
2755            serialized.len()
2756        );
2757
2758        //deserialize and check that everything is as expected
2759        use std::io::Cursor;
2760        use std::io::Read;
2761        //deserialize each part of the message and check it
2762        let mut cursor = Cursor::new(&serialized);
2763
2764        //ethernet 2 header
2765        assert_eq!(
2766            Ethernet2Header::read(&mut cursor).unwrap(),
2767            Ethernet2Header {
2768                source: [1, 2, 3, 4, 5, 6],
2769                destination: [7, 8, 9, 10, 11, 12],
2770                ether_type: ether_type::IPV6
2771            }
2772        );
2773
2774        //ip header
2775        let ip_actual = Ipv6Header::read(&mut cursor).unwrap();
2776        let ip_expected = Ipv6Header {
2777            traffic_class: 0,
2778            flow_label: Ipv6FlowLabel::ZERO,
2779            payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
2780            next_header: ip_number::UDP,
2781            hop_limit: 47,
2782            source: [
2783                11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
2784            ],
2785            destination: [
2786                31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
2787            ],
2788        };
2789        assert_eq!(ip_actual, ip_expected);
2790
2791        //udp header
2792        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
2793        let udp_expected =
2794            UdpHeader::with_ipv6_checksum(48, 49, &ip_expected, &in_payload).unwrap();
2795        assert_eq!(udp_actual, udp_expected);
2796
2797        //payload
2798        let mut actual_payload: [u8; 4] = [0; 4];
2799        cursor.read_exact(&mut actual_payload).unwrap();
2800        assert_eq!(actual_payload, in_payload);
2801    }
2802
2803    #[test]
2804    fn linuxsll_ipv6_udp() {
2805        //generate
2806        let in_payload = [50, 51, 52, 53];
2807        let mut serialized = Vec::new();
2808        PacketBuilder::linux_sll(LinuxSllPacketType::OUTGOING, 6, [7, 8, 9, 10, 11, 12, 0, 0])
2809            .ipv6(
2810                [
2811                    11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
2812                ],
2813                [
2814                    31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
2815                ],
2816                47,
2817            )
2818            .udp(48, 49)
2819            .write(&mut serialized, &in_payload)
2820            .unwrap();
2821
2822        //check the deserialized size
2823        assert_eq!(
2824            LinuxSllHeader::LEN + Ipv6Header::LEN + UdpHeader::LEN + in_payload.len(),
2825            serialized.len()
2826        );
2827
2828        //deserialize and check that everything is as expected
2829        use std::io::Cursor;
2830        use std::io::Read;
2831        //deserialize each part of the message and check it
2832        let mut cursor = Cursor::new(&serialized);
2833
2834        //ethernet 2 header
2835        assert_eq!(
2836            LinuxSllHeader::read(&mut cursor).unwrap(),
2837            LinuxSllHeader {
2838                packet_type: LinuxSllPacketType::OUTGOING,
2839                arp_hrd_type: ArpHardwareId::ETHERNET,
2840                sender_address_valid_length: 6,
2841                sender_address: [7, 8, 9, 10, 11, 12, 0, 0],
2842                protocol_type: LinuxSllProtocolType::EtherType(EtherType::IPV6)
2843            }
2844        );
2845
2846        //ip header
2847        let ip_actual = Ipv6Header::read(&mut cursor).unwrap();
2848        let ip_expected = Ipv6Header {
2849            traffic_class: 0,
2850            flow_label: Ipv6FlowLabel::ZERO,
2851            payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
2852            next_header: ip_number::UDP,
2853            hop_limit: 47,
2854            source: [
2855                11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
2856            ],
2857            destination: [
2858                31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
2859            ],
2860        };
2861        assert_eq!(ip_actual, ip_expected);
2862
2863        //udp header
2864        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
2865        let udp_expected =
2866            UdpHeader::with_ipv6_checksum(48, 49, &ip_expected, &in_payload).unwrap();
2867        assert_eq!(udp_actual, udp_expected);
2868
2869        //payload
2870        let mut actual_payload: [u8; 4] = [0; 4];
2871        cursor.read_exact(&mut actual_payload).unwrap();
2872        assert_eq!(actual_payload, in_payload);
2873    }
2874
2875    #[test]
2876    fn eth_single_vlan_ipv4_udp() {
2877        //generate
2878        let in_payload = [50, 51, 52, 53];
2879        let mut serialized = Vec::new();
2880        PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
2881            .single_vlan(0x123.try_into().unwrap())
2882            .ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
2883            .udp(48, 49)
2884            .write(&mut serialized, &in_payload)
2885            .unwrap();
2886
2887        //check the deserialized size
2888
2889        //check the deserialized size
2890        let expected_ip_size: usize = UdpHeader::LEN + in_payload.len();
2891        assert_eq!(
2892            expected_ip_size + Ethernet2Header::LEN + Ipv4Header::MIN_LEN + SingleVlanHeader::LEN,
2893            serialized.len()
2894        );
2895
2896        //deserialize and check that everything is as expected
2897        use std::io::Cursor;
2898        use std::io::Read;
2899        //deserialize each part of the message and check it
2900        let mut cursor = Cursor::new(&serialized);
2901
2902        //ethernet 2 header
2903        assert_eq!(
2904            Ethernet2Header::read(&mut cursor).unwrap(),
2905            Ethernet2Header {
2906                source: [1, 2, 3, 4, 5, 6],
2907                destination: [7, 8, 9, 10, 11, 12],
2908                ether_type: ether_type::VLAN_TAGGED_FRAME
2909            }
2910        );
2911
2912        //vlan header
2913        assert_eq!(
2914            SingleVlanHeader::read(&mut cursor).unwrap(),
2915            SingleVlanHeader {
2916                pcp: VlanPcp::ZERO,
2917                drop_eligible_indicator: false,
2918                vlan_id: 0x123.try_into().unwrap(),
2919                ether_type: ether_type::IPV4
2920            }
2921        );
2922
2923        //ip header
2924        let ip_actual = Ipv4Header::read(&mut cursor).unwrap();
2925        let mut ip_expected = Ipv4Header::new(
2926            expected_ip_size as u16, //payload_len
2927            21,                      //ttl
2928            ip_number::UDP,
2929            [13, 14, 15, 16],
2930            [17, 18, 19, 20],
2931        )
2932        .unwrap();
2933        ip_expected.header_checksum = ip_expected.calc_header_checksum();
2934        assert_eq!(ip_actual, ip_expected);
2935
2936        //udp header
2937        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
2938        let udp_expected =
2939            UdpHeader::with_ipv4_checksum(48, 49, &ip_expected, &in_payload).unwrap();
2940        assert_eq!(udp_actual, udp_expected);
2941
2942        //payload
2943        let mut actual_payload: [u8; 4] = [0; 4];
2944        cursor.read_exact(&mut actual_payload).unwrap();
2945        assert_eq!(actual_payload, in_payload);
2946    }
2947
2948    #[test]
2949    fn eth_double_vlan_ipv6_udp() {
2950        //generate
2951        let in_payload = [50, 51, 52, 53];
2952        let mut serialized = Vec::new();
2953        PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
2954            .double_vlan(0x123.try_into().unwrap(), 0x234.try_into().unwrap())
2955            .ipv6(
2956                [
2957                    11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
2958                ],
2959                [
2960                    31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
2961                ],
2962                47,
2963            )
2964            .udp(48, 49)
2965            .write(&mut serialized, &in_payload)
2966            .unwrap();
2967
2968        //check the deserialized size
2969        assert_eq!(
2970            Ethernet2Header::LEN
2971                + SingleVlanHeader::LEN * 2
2972                + Ipv6Header::LEN
2973                + UdpHeader::LEN
2974                + in_payload.len(),
2975            serialized.len()
2976        );
2977
2978        //deserialize and check that everything is as expected
2979        use std::io::Cursor;
2980        use std::io::Read;
2981
2982        //deserialize each part of the message and check it
2983        let mut cursor = Cursor::new(&serialized);
2984
2985        //ethernet 2 header
2986        assert_eq!(
2987            Ethernet2Header::read(&mut cursor).unwrap(),
2988            Ethernet2Header {
2989                source: [1, 2, 3, 4, 5, 6],
2990                destination: [7, 8, 9, 10, 11, 12],
2991                ether_type: ether_type::PROVIDER_BRIDGING,
2992            }
2993        );
2994
2995        //outer vlan header
2996        assert_eq!(
2997            SingleVlanHeader::read(&mut cursor).unwrap(),
2998            SingleVlanHeader {
2999                pcp: VlanPcp::ZERO,
3000                drop_eligible_indicator: false,
3001                vlan_id: 0x123.try_into().unwrap(),
3002                ether_type: ether_type::VLAN_TAGGED_FRAME
3003            }
3004        );
3005
3006        //inner vlan header
3007        assert_eq!(
3008            SingleVlanHeader::read(&mut cursor).unwrap(),
3009            SingleVlanHeader {
3010                pcp: VlanPcp::ZERO,
3011                drop_eligible_indicator: false,
3012                vlan_id: 0x234.try_into().unwrap(),
3013                ether_type: ether_type::IPV6
3014            }
3015        );
3016
3017        //ip header
3018        let ip_actual = Ipv6Header::read(&mut cursor).unwrap();
3019        let ip_expected = Ipv6Header {
3020            traffic_class: 0,
3021            flow_label: Ipv6FlowLabel::ZERO,
3022            payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
3023            next_header: ip_number::UDP,
3024            hop_limit: 47,
3025            source: [
3026                11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
3027            ],
3028            destination: [
3029                31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
3030            ],
3031        };
3032        assert_eq!(ip_actual, ip_expected);
3033
3034        //udp header
3035        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
3036        let udp_expected =
3037            UdpHeader::with_ipv6_checksum(48, 49, &ip_expected, &in_payload).unwrap();
3038        assert_eq!(udp_actual, udp_expected);
3039
3040        //payload
3041        let mut actual_payload: [u8; 4] = [0; 4];
3042        cursor.read_exact(&mut actual_payload).unwrap();
3043        assert_eq!(actual_payload, in_payload);
3044    }
3045
3046    #[test]
3047    fn eth_ip_udp() {
3048        //generate
3049        let in_payload = [50, 51, 52, 53];
3050        let mut serialized = Vec::new();
3051        PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
3052            .ip(IpHeaders::Ipv6(
3053                Ipv6Header {
3054                    traffic_class: 1,
3055                    flow_label: 2.try_into().unwrap(),
3056                    payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
3057                    next_header: ip_number::UDP,
3058                    hop_limit: 47,
3059                    source: [
3060                        11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
3061                    ],
3062                    destination: [
3063                        31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
3064                    ],
3065                },
3066                Default::default(),
3067            ))
3068            .udp(48, 49)
3069            .write(&mut serialized, &in_payload)
3070            .unwrap();
3071
3072        //check the deserialized size
3073        assert_eq!(
3074            Ethernet2Header::LEN + Ipv6Header::LEN + UdpHeader::LEN + in_payload.len(),
3075            serialized.len()
3076        );
3077
3078        //deserialize and check that everything is as expected
3079        use std::io::Cursor;
3080        use std::io::Read;
3081
3082        //deserialize each part of the message and check it
3083        let mut cursor = Cursor::new(&serialized);
3084
3085        //ethernet 2 header
3086        assert_eq!(
3087            Ethernet2Header::read(&mut cursor).unwrap(),
3088            Ethernet2Header {
3089                source: [1, 2, 3, 4, 5, 6],
3090                destination: [7, 8, 9, 10, 11, 12],
3091                ether_type: ether_type::IPV6
3092            }
3093        );
3094
3095        //ip header
3096        let ip_actual = Ipv6Header::read(&mut cursor).unwrap();
3097        let ip_expected = Ipv6Header {
3098            traffic_class: 1,
3099            flow_label: 2.try_into().unwrap(),
3100            payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
3101            next_header: ip_number::UDP,
3102            hop_limit: 47,
3103            source: [
3104                11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
3105            ],
3106            destination: [
3107                31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
3108            ],
3109        };
3110        assert_eq!(ip_actual, ip_expected);
3111
3112        //udp header
3113        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
3114        let udp_expected =
3115            UdpHeader::with_ipv6_checksum(48, 49, &ip_expected, &in_payload).unwrap();
3116        assert_eq!(udp_actual, udp_expected);
3117
3118        //payload
3119        let mut actual_payload: [u8; 4] = [0; 4];
3120        cursor.read_exact(&mut actual_payload).unwrap();
3121        assert_eq!(actual_payload, in_payload);
3122    }
3123
3124    #[test]
3125    fn linuxsll_ip_udp() {
3126        //generate
3127        let in_payload = [50, 51, 52, 53];
3128        let mut serialized = Vec::new();
3129        PacketBuilder::linux_sll(LinuxSllPacketType::OUTGOING, 6, [7, 8, 9, 10, 11, 12, 0, 0])
3130            .ip(IpHeaders::Ipv6(
3131                Ipv6Header {
3132                    traffic_class: 1,
3133                    flow_label: 2.try_into().unwrap(),
3134                    payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
3135                    next_header: ip_number::UDP,
3136                    hop_limit: 47,
3137                    source: [
3138                        11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
3139                    ],
3140                    destination: [
3141                        31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
3142                    ],
3143                },
3144                Default::default(),
3145            ))
3146            .udp(48, 49)
3147            .write(&mut serialized, &in_payload)
3148            .unwrap();
3149
3150        //check the deserialized size
3151        assert_eq!(
3152            LinuxSllHeader::LEN + Ipv6Header::LEN + UdpHeader::LEN + in_payload.len(),
3153            serialized.len()
3154        );
3155
3156        //deserialize and check that everything is as expected
3157        use std::io::Cursor;
3158        use std::io::Read;
3159
3160        //deserialize each part of the message and check it
3161        let mut cursor = Cursor::new(&serialized);
3162
3163        //ethernet 2 header
3164        assert_eq!(
3165            LinuxSllHeader::read(&mut cursor).unwrap(),
3166            LinuxSllHeader {
3167                packet_type: LinuxSllPacketType::OUTGOING,
3168                arp_hrd_type: ArpHardwareId::ETHERNET,
3169                sender_address_valid_length: 6,
3170                sender_address: [7, 8, 9, 10, 11, 12, 0, 0],
3171                protocol_type: LinuxSllProtocolType::EtherType(EtherType::IPV6)
3172            }
3173        );
3174
3175        //ip header
3176        let ip_actual = Ipv6Header::read(&mut cursor).unwrap();
3177        let ip_expected = Ipv6Header {
3178            traffic_class: 1,
3179            flow_label: 2.try_into().unwrap(),
3180            payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
3181            next_header: ip_number::UDP,
3182            hop_limit: 47,
3183            source: [
3184                11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
3185            ],
3186            destination: [
3187                31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
3188            ],
3189        };
3190        assert_eq!(ip_actual, ip_expected);
3191
3192        //udp header
3193        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
3194        let udp_expected =
3195            UdpHeader::with_ipv6_checksum(48, 49, &ip_expected, &in_payload).unwrap();
3196        assert_eq!(udp_actual, udp_expected);
3197
3198        //payload
3199        let mut actual_payload: [u8; 4] = [0; 4];
3200        cursor.read_exact(&mut actual_payload).unwrap();
3201        assert_eq!(actual_payload, in_payload);
3202    }
3203
3204    #[test]
3205    fn eth_vlan_ip_udp() {
3206        //generate
3207        let in_payload = [50, 51, 52, 53];
3208        let mut serialized = Vec::new();
3209        PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
3210            .vlan(VlanHeader::Single(SingleVlanHeader {
3211                pcp: 1.try_into().unwrap(),
3212                drop_eligible_indicator: true,
3213                vlan_id: 0x123.try_into().unwrap(),
3214                ether_type: 0.into(), //should be overwritten
3215            }))
3216            .ip(IpHeaders::Ipv6(
3217                Ipv6Header {
3218                    traffic_class: 1,
3219                    flow_label: 2.try_into().unwrap(),
3220                    payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
3221                    next_header: ip_number::UDP,
3222                    hop_limit: 47,
3223                    source: [
3224                        11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
3225                    ],
3226                    destination: [
3227                        31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
3228                    ],
3229                },
3230                Default::default(),
3231            ))
3232            .udp(48, 49)
3233            .write(&mut serialized, &in_payload)
3234            .unwrap();
3235
3236        //check the deserialized size
3237        assert_eq!(
3238            Ethernet2Header::LEN
3239                + SingleVlanHeader::LEN
3240                + Ipv6Header::LEN
3241                + UdpHeader::LEN
3242                + in_payload.len(),
3243            serialized.len()
3244        );
3245
3246        //deserialize and check that everything is as expected
3247        use std::io::Cursor;
3248        use std::io::Read;
3249
3250        //deserialize each part of the message and check it
3251        let mut cursor = Cursor::new(&serialized);
3252
3253        //ethernet 2 header
3254        assert_eq!(
3255            Ethernet2Header::read(&mut cursor).unwrap(),
3256            Ethernet2Header {
3257                source: [1, 2, 3, 4, 5, 6],
3258                destination: [7, 8, 9, 10, 11, 12],
3259                ether_type: ether_type::VLAN_TAGGED_FRAME
3260            }
3261        );
3262
3263        //outer vlan header
3264        assert_eq!(
3265            SingleVlanHeader::read(&mut cursor).unwrap(),
3266            SingleVlanHeader {
3267                pcp: 1.try_into().unwrap(),
3268                drop_eligible_indicator: true,
3269                vlan_id: 0x123.try_into().unwrap(),
3270                ether_type: ether_type::IPV6
3271            }
3272        );
3273
3274        //ip header
3275        let ip_actual = Ipv6Header::read(&mut cursor).unwrap();
3276        let ip_expected = Ipv6Header {
3277            traffic_class: 1,
3278            flow_label: 2.try_into().unwrap(),
3279            payload_length: (UdpHeader::LEN + in_payload.len()) as u16,
3280            next_header: ip_number::UDP,
3281            hop_limit: 47,
3282            source: [
3283                11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26,
3284            ],
3285            destination: [
3286                31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
3287            ],
3288        };
3289        assert_eq!(ip_actual, ip_expected);
3290
3291        //udp header
3292        let udp_actual = UdpHeader::read(&mut cursor).unwrap();
3293        let udp_expected =
3294            UdpHeader::with_ipv6_checksum(48, 49, &ip_expected, &in_payload).unwrap();
3295        assert_eq!(udp_actual, udp_expected);
3296
3297        //payload
3298        let mut actual_payload: [u8; 4] = [0; 4];
3299        cursor.read_exact(&mut actual_payload).unwrap();
3300        assert_eq!(actual_payload, in_payload);
3301    }
3302
3303    proptest! {
3304        #[test]
3305        fn tcp_ipv4(ref input in tcp_any()) {
3306
3307            //payload
3308            let in_payload = [24,25,26,27];
3309
3310            //ip v4 header
3311            let mut ip_expected = Ipv4Header::new(
3312                in_payload.len() as u16 + input.header_len_u16(),
3313                21, //ttl
3314                ip_number::TCP,
3315                [13,14,15,16],
3316                [17,18,19,20]
3317            ).unwrap();
3318            ip_expected.header_checksum = ip_expected.calc_header_checksum();
3319
3320            //generated the expected output
3321            let expected = {
3322                let mut expected = input.clone();
3323                //replace urg & ack if the flags are not set
3324                if !expected.ack {
3325                    expected.acknowledgment_number = 0;
3326                }
3327                if !expected.urg {
3328                    expected.urgent_pointer = 0;
3329                }
3330                //calculate the checksum
3331                expected.checksum = expected.calc_checksum_ipv4(&ip_expected, &in_payload[..]).unwrap();
3332                //done
3333                expected
3334            };
3335
3336            //generate
3337            let serialized = {
3338
3339                //create builder
3340                let mut builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3341                                                .ipv4([13,14,15,16], [17,18,19,20], 21)
3342                                                .tcp(input.source_port,
3343                                                    input.destination_port,
3344                                                    input.sequence_number,
3345                                                    input.window_size)
3346                                                .options_raw(input.options.as_slice()).unwrap();
3347                //set the flags
3348                if input.ns {
3349                    builder = builder.ns();
3350                }
3351                if input.fin {
3352                    builder = builder.fin();
3353                }
3354                if input.syn {
3355                    builder = builder.syn();
3356                }
3357                if input.rst {
3358                    builder = builder.rst();
3359                }
3360                if input.psh {
3361                    builder = builder.psh();
3362                }
3363                if input.ack {
3364                    builder = builder.ack(input.acknowledgment_number);
3365                }
3366                if input.urg {
3367                    builder = builder.urg(input.urgent_pointer);
3368                }
3369                if input.ece {
3370                    builder = builder.ece();
3371                }
3372                if input.cwr {
3373                    builder = builder.cwr();
3374                }
3375
3376                let mut serialized = Vec::new();
3377                builder.write(&mut serialized, &in_payload).unwrap();
3378                serialized
3379            };
3380
3381            //deserialize and check that everything is as expected
3382            use std::io::Cursor;
3383            use std::io::Read;
3384            //deserialize each part of the message and check it
3385            let mut cursor = Cursor::new(&serialized);
3386
3387            //ethernet 2 header
3388            assert_eq!(Ethernet2Header::read(&mut cursor).unwrap(),
3389                    Ethernet2Header{
3390                            source: [1,2,3,4,5,6],
3391                            destination: [7,8,9,10,11,12],
3392                            ether_type: ether_type::IPV4
3393                    });
3394
3395            //ip header
3396            let ip_actual = Ipv4Header::read(&mut cursor).unwrap();
3397            assert_eq!(ip_actual,
3398                    ip_expected);
3399
3400            //tcp header
3401            assert_eq!(TcpHeader::read(&mut cursor).unwrap(),
3402                    expected);
3403
3404            //payload
3405            let mut actual_payload: [u8;4] = [0;4];
3406            cursor.read_exact(&mut actual_payload).unwrap();
3407            assert_eq!(actual_payload, in_payload);
3408        }
3409    }
3410
3411    proptest! {
3412        #[test]
3413        fn tcp_ipv6(ref input in tcp_any()) {
3414
3415            //payload
3416            let in_payload = [24,25,26,27];
3417
3418            //ip v4 header
3419            let ip_expected = Ipv6Header{
3420                traffic_class: 0,
3421                flow_label: Ipv6FlowLabel::ZERO,
3422                payload_length: (input.header_len() as usize + in_payload.len()) as u16,
3423                next_header: ip_number::TCP,
3424                hop_limit: 47,
3425                source: [11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
3426                destination: [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46]
3427            };
3428
3429            //generated the expected output
3430            let expected = {
3431                let mut expected = input.clone();
3432                //replace urg & ack if the flags are not set
3433                if !expected.ack {
3434                    expected.acknowledgment_number = 0;
3435                }
3436                if !expected.urg {
3437                    expected.urgent_pointer = 0;
3438                }
3439                //calculate the checksum
3440                expected.checksum = expected.calc_checksum_ipv6(&ip_expected, &in_payload[..]).unwrap();
3441                //done
3442                expected
3443            };
3444
3445            //generate
3446            let serialized = {
3447
3448                //create builder
3449                let mut builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3450                                                .ipv6([11,12,13,14,15,16,17,18,19,10,21,22,23,24,25,26],
3451                                                    [31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],
3452                                                    47,
3453                                                )
3454                                                .tcp(input.source_port,
3455                                                    input.destination_port,
3456                                                    input.sequence_number,
3457                                                    input.window_size)
3458                                                .options_raw(input.options.as_slice()).unwrap();
3459                //set the flags
3460                if input.ns {
3461                    builder = builder.ns();
3462                }
3463                if input.fin {
3464                    builder = builder.fin();
3465                }
3466                if input.syn {
3467                    builder = builder.syn();
3468                }
3469                if input.rst {
3470                    builder = builder.rst();
3471                }
3472                if input.psh {
3473                    builder = builder.psh();
3474                }
3475                if input.ack {
3476                    builder = builder.ack(input.acknowledgment_number);
3477                }
3478                if input.urg {
3479                    builder = builder.urg(input.urgent_pointer);
3480                }
3481                if input.ece {
3482                    builder = builder.ece();
3483                }
3484                if input.cwr {
3485                    builder = builder.cwr();
3486                }
3487
3488                let mut serialized = Vec::new();
3489                builder.write(&mut serialized, &in_payload).unwrap();
3490                serialized
3491            };
3492
3493            //deserialize and check that everything is as expected
3494            use std::io::Cursor;
3495            use std::io::Read;
3496            //deserialize each part of the message and check it
3497            let mut cursor = Cursor::new(&serialized);
3498
3499            //ethernet 2 header
3500            assert_eq!(Ethernet2Header::read(&mut cursor).unwrap(),
3501                    Ethernet2Header{
3502                            source: [1,2,3,4,5,6],
3503                            destination: [7,8,9,10,11,12],
3504                            ether_type: ether_type::IPV6
3505                    });
3506
3507            //ip header
3508            let ip_actual = Ipv6Header::read(&mut cursor).unwrap();
3509            assert_eq!(ip_actual,
3510                    ip_expected);
3511
3512            //tcp header
3513            assert_eq!(TcpHeader::read(&mut cursor).unwrap(),
3514                    expected);
3515
3516            //payload
3517            let mut actual_payload: [u8;4] = [0;4];
3518            cursor.read_exact(&mut actual_payload).unwrap();
3519            assert_eq!(actual_payload, in_payload);
3520        }
3521    }
3522
3523    #[test]
3524    fn eth_ipv4_tcp_options() {
3525        let mut serialized = Vec::new();
3526
3527        use crate::TcpOptionElement::*;
3528        let options = vec![MaximumSegmentSize(1234), Noop];
3529
3530        PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
3531            .ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
3532            .tcp(1, 2, 3, 4)
3533            .options(&options)
3534            .unwrap()
3535            .write(&mut serialized, &[])
3536            .unwrap();
3537
3538        let decoded = PacketHeaders::from_ethernet_slice(&serialized[..]).unwrap();
3539        let dec_options: Vec<Result<TcpOptionElement, TcpOptionReadError>> = decoded
3540            .transport
3541            .unwrap()
3542            .tcp()
3543            .unwrap()
3544            .options_iterator()
3545            .collect();
3546        assert_eq!(&[Ok(MaximumSegmentSize(1234)), Ok(Noop)], &dec_options[..]);
3547    }
3548
3549    #[test]
3550    fn eth_ipv4_tcp_header() {
3551        let mut serialized = Vec::new();
3552
3553        let tcp_header = TcpHeader {
3554            source_port: 1234,
3555            destination_port: 2345,
3556            sequence_number: 3456,
3557            acknowledgment_number: 4567,
3558            ..Default::default()
3559        };
3560
3561        PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
3562            .ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
3563            .tcp_header(tcp_header.clone())
3564            .write(&mut serialized, &[])
3565            .unwrap();
3566
3567        let decoded = PacketHeaders::from_ethernet_slice(&serialized[..]).unwrap();
3568
3569        let mut expected = tcp_header;
3570        expected.checksum = expected
3571            .calc_checksum_ipv4_raw([13, 14, 15, 16], [17, 18, 19, 20], &[])
3572            .unwrap();
3573
3574        assert_eq!(decoded.transport, Some(TransportHeader::Tcp(expected)));
3575    }
3576
3577    #[test]
3578    fn size() {
3579        //ipv4 no vlan ethernet
3580        assert_eq!(
3581            Ethernet2Header::LEN + Ipv4Header::MIN_LEN + UdpHeader::LEN + 123,
3582            PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
3583                .ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
3584                .udp(22, 23)
3585                .size(123)
3586        );
3587
3588        //ipv6 no vlan ethernet
3589        assert_eq!(
3590            Ethernet2Header::LEN + Ipv6Header::LEN + UdpHeader::LEN + 123,
3591            PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
3592                .ipv6(
3593                    [11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26],
3594                    [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46],
3595                    47,
3596                )
3597                .udp(22, 23)
3598                .size(123)
3599        );
3600
3601        //ipv4 linux_sll
3602        assert_eq!(
3603            LinuxSllHeader::LEN + Ipv4Header::MIN_LEN + UdpHeader::LEN + 123,
3604            PacketBuilder::linux_sll(LinuxSllPacketType::OUTGOING, 6, [7, 8, 9, 10, 11, 12, 0, 0])
3605                .ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
3606                .udp(22, 23)
3607                .size(123)
3608        );
3609
3610        //ipv6 linux_sll
3611        assert_eq!(
3612            LinuxSllHeader::LEN + Ipv6Header::LEN + UdpHeader::LEN + 123,
3613            PacketBuilder::linux_sll(LinuxSllPacketType::OUTGOING, 6, [7, 8, 9, 10, 11, 12, 0, 0])
3614                .ipv6(
3615                    [11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26],
3616                    [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46],
3617                    47,
3618                )
3619                .udp(22, 23)
3620                .size(123)
3621        );
3622
3623        //ipv4 single vlan ethernet
3624        assert_eq!(
3625            Ethernet2Header::LEN
3626                + SingleVlanHeader::LEN
3627                + Ipv4Header::MIN_LEN
3628                + UdpHeader::LEN
3629                + 123,
3630            PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
3631                .single_vlan(0x123.try_into().unwrap())
3632                .ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
3633                .udp(22, 23)
3634                .size(123)
3635        );
3636
3637        //ipv6 double vlan ethernet
3638        assert_eq!(
3639            Ethernet2Header::LEN
3640                + SingleVlanHeader::LEN * 2
3641                + Ipv6Header::LEN
3642                + UdpHeader::LEN
3643                + 123,
3644            PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
3645                .double_vlan(0x123.try_into().unwrap(), 0x234.try_into().unwrap())
3646                .ipv6(
3647                    [11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26],
3648                    [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46],
3649                    47,
3650                )
3651                .udp(22, 23)
3652                .size(123)
3653        );
3654    }
3655
3656    proptest! {
3657        #[test]
3658        fn size_tcp(ref input in tcp_any()) {
3659
3660            assert_eq!(Ethernet2Header::LEN +
3661                    Ipv4Header::MIN_LEN +
3662                    input.header_len() as usize +
3663                    123,
3664
3665                    PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3666                                    .ipv4([13,14,15,16], [17,18,19,20], 21)
3667                                    .tcp(input.source_port,
3668                                        input.destination_port,
3669                                        input.sequence_number,
3670                                        input.window_size)
3671                                    .options_raw(input.options.as_slice()).unwrap()
3672                                    .size(123));
3673        }
3674    }
3675
3676    proptest! {
3677        #[test]
3678        fn ipv4_icmpv4(
3679            ipv4_source in any::<[u8;4]>(),
3680            ipv4_dest in any::<[u8;4]>(),
3681            ipv4_time_to_live in any::<u8>(),
3682            icmpv4_type_u8 in 15u8..u8::MAX,
3683            icmpv4_code_u8 in any::<u8>(),
3684            icmpv4_bytes5to8 in any::<[u8;4]>(),
3685            icmpv4 in icmpv4_type_any(),
3686            echo_id in any::<u16>(),
3687            echo_seq in any::<u16>(),
3688            payload in proptest::collection::vec(any::<u8>(), 0..64),
3689        ) {
3690            let test_builder = |builder: PacketBuilderStep<Icmpv4Header>, icmpv4_type: Icmpv4Type| {
3691                use crate::Icmpv4Type::*;
3692                let adapted_payload = match &icmpv4_type {
3693                    TimestampRequest(_) |
3694                    TimestampReply(_) => &[],
3695                    _ => &payload[..],
3696                };
3697                let icmp_expected = Icmpv4Header::with_checksum(icmpv4_type, &adapted_payload);
3698                let ip_expected = {
3699                    let mut expected_ipv4 = Ipv4Header::new(
3700                        (icmp_expected.header_len() + adapted_payload.len()) as u16,
3701                        ipv4_time_to_live,
3702                        ip_number::ICMP,
3703                        ipv4_source,
3704                        ipv4_dest
3705                    ).unwrap();
3706                    expected_ipv4.header_checksum = expected_ipv4.calc_header_checksum();
3707                    expected_ipv4
3708                };
3709
3710                // test builder.size()
3711                assert_eq!(
3712                    builder.size(adapted_payload.len()),
3713                    Ethernet2Header::LEN +
3714                    Ipv4Header::MIN_LEN +
3715                    icmp_expected.header_len() +
3716                    adapted_payload.len()
3717                );
3718
3719                // test builder.write()
3720                let mut buffer = Vec::<u8>::with_capacity(builder.size(adapted_payload.len()));
3721                builder.write(&mut buffer, adapted_payload).unwrap();
3722
3723                // decode packets
3724                let actual = PacketHeaders::from_ethernet_slice(&buffer).unwrap();
3725
3726                // check the packets could be decoded
3727                assert_eq!(
3728                    Some(LinkHeader::Ethernet2(Ethernet2Header{
3729                        source: [1,2,3,4,5,6],
3730                        destination: [7,8,9,10,11,12],
3731                        ether_type: ether_type::IPV4
3732                    })),
3733                    actual.link
3734                );
3735                assert_eq!(
3736                    Some(NetHeaders::Ipv4(ip_expected, Default::default())),
3737                    actual.net
3738                );
3739                assert_eq!(
3740                    Some(TransportHeader::Icmpv4(icmp_expected)),
3741                    actual.transport
3742                );
3743                assert_eq!(actual.payload.slice(), adapted_payload);
3744            };
3745
3746            // icmpv4
3747            {
3748                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3749                    .ipv4(ipv4_source, ipv4_dest, ipv4_time_to_live)
3750                    .icmpv4(icmpv4.clone());
3751
3752                test_builder(
3753                    builder,
3754                    icmpv4
3755                );
3756            }
3757
3758            // icmpv4_raw
3759            {
3760                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3761                    .ipv4(ipv4_source, ipv4_dest, ipv4_time_to_live)
3762                    .icmpv4_raw(icmpv4_type_u8, icmpv4_code_u8, icmpv4_bytes5to8);
3763
3764                test_builder(
3765                    builder,
3766                    Icmpv4Type::Unknown{
3767                        type_u8: icmpv4_type_u8,
3768                        code_u8: icmpv4_code_u8,
3769                        bytes5to8: icmpv4_bytes5to8,
3770                    }
3771                );
3772            }
3773
3774            // icmpv4_echo_request
3775            {
3776                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3777                    .ipv4(ipv4_source, ipv4_dest, ipv4_time_to_live)
3778                    .icmpv4_echo_request(echo_id, echo_seq);
3779
3780                test_builder(
3781                    builder,
3782                    Icmpv4Type::EchoRequest(IcmpEchoHeader{
3783                        id: echo_id,
3784                        seq: echo_seq,
3785                    })
3786                );
3787            }
3788
3789            // icmp4_echo_reply
3790            {
3791                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3792                    .ipv4(ipv4_source, ipv4_dest, ipv4_time_to_live)
3793                    .icmpv4_echo_reply(echo_id, echo_seq);
3794
3795                test_builder(
3796                    builder,
3797                    Icmpv4Type::EchoReply(IcmpEchoHeader{
3798                        id: echo_id,
3799                        seq: echo_seq,
3800                    })
3801                );
3802            }
3803        }
3804    }
3805
3806    proptest! {
3807        #[test]
3808        fn ipv4_icmpv6(
3809            ipv4_source in any::<[u8;4]>(),
3810            ipv4_dest in any::<[u8;4]>(),
3811            ipv4_time_to_live in any::<u8>(),
3812            icmpv6_type_u8 in 162u8..u8::MAX,
3813            icmpv6_code_u8 in any::<u8>(),
3814            icmpv6_bytes5to8 in any::<[u8;4]>(),
3815            icmpv6 in icmpv6_type_any(),
3816            echo_id in any::<u16>(),
3817            echo_seq in any::<u16>(),
3818            payload in proptest::collection::vec(any::<u8>(), 0..64),
3819        ) {
3820            let test_builder = |builder: PacketBuilderStep<Icmpv6Header>, icmpv6_type: Icmpv6Type| {
3821                // test builder.size()
3822                assert_eq!(
3823                    builder.size(payload.len()),
3824                    Ethernet2Header::LEN +
3825                    Ipv4Header::MIN_LEN +
3826                    icmpv6_type.header_len() +
3827                    payload.len()
3828                );
3829
3830                // test builder.write()
3831                let mut buffer = Vec::<u8>::with_capacity(builder.size(payload.len()));
3832                // should trigger an error, was it is not possible to calculate the checksum
3833                assert!(builder.write(&mut buffer, &payload).is_err());
3834            };
3835
3836            // icmpv6
3837            {
3838                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3839                    .ipv4(ipv4_source, ipv4_dest, ipv4_time_to_live)
3840                    .icmpv6(icmpv6.clone());
3841
3842                test_builder(
3843                    builder,
3844                    icmpv6
3845                );
3846            }
3847
3848            // icmpv6_raw
3849            {
3850                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3851                    .ipv4(ipv4_source, ipv4_dest, ipv4_time_to_live)
3852                    .icmpv6_raw(icmpv6_type_u8, icmpv6_code_u8, icmpv6_bytes5to8);
3853
3854                test_builder(
3855                    builder,
3856                    Icmpv6Type::Unknown{
3857                        type_u8: icmpv6_type_u8,
3858                        code_u8: icmpv6_code_u8,
3859                        bytes5to8: icmpv6_bytes5to8,
3860                    }
3861                );
3862            }
3863
3864            // icmpv6_echo_request
3865            {
3866                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3867                    .ipv4(ipv4_source, ipv4_dest, ipv4_time_to_live)
3868                    .icmpv6_echo_request(echo_id, echo_seq);
3869
3870                test_builder(
3871                    builder,
3872                    Icmpv6Type::EchoRequest(IcmpEchoHeader{
3873                        id: echo_id,
3874                        seq: echo_seq,
3875                    })
3876                );
3877            }
3878
3879            // icmp4_echo_reply
3880            {
3881                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3882                    .ipv4(ipv4_source, ipv4_dest, ipv4_time_to_live)
3883                    .icmpv6_echo_reply(echo_id, echo_seq);
3884
3885                test_builder(
3886                    builder,
3887                    Icmpv6Type::EchoReply(IcmpEchoHeader{
3888                        id: echo_id,
3889                        seq: echo_seq,
3890                    })
3891                );
3892            }
3893        }
3894    }
3895
3896    proptest! {
3897        #[test]
3898        fn ipv6_icmpv4(
3899            ipv6_source in any::<[u8;16]>(),
3900            ipv6_dest in any::<[u8;16]>(),
3901            ipv6_hop_limit in any::<u8>(),
3902            icmpv4_type_u8 in 15u8..u8::MAX,
3903            icmpv4_code_u8 in any::<u8>(),
3904            icmpv4_bytes5to8 in any::<[u8;4]>(),
3905            icmpv4 in icmpv4_type_any(),
3906            echo_id in any::<u16>(),
3907            echo_seq in any::<u16>(),
3908            payload in proptest::collection::vec(any::<u8>(), 0..64),
3909        ) {
3910            let test_builder = |builder: PacketBuilderStep<Icmpv4Header>, icmpv4_type: Icmpv4Type| {
3911
3912                use Icmpv4Type::*;
3913                let adapted_payload = match icmpv4_type {
3914                    TimestampRequest(_) | TimestampReply(_) => &[],
3915                    _ => &payload[..],
3916                };
3917
3918                let icmp_expected = Icmpv4Header::with_checksum(icmpv4_type, &adapted_payload);
3919                let ip_expected = Ipv6Header{
3920                    traffic_class: 0,
3921                    flow_label: Ipv6FlowLabel::ZERO,
3922                    payload_length: (icmp_expected.header_len() + adapted_payload.len()) as u16,
3923                    next_header: ip_number::ICMP,
3924                    hop_limit: ipv6_hop_limit,
3925                    source: ipv6_source,
3926                    destination: ipv6_dest
3927                };
3928
3929                // test builder.size()
3930                assert_eq!(
3931                    builder.size(adapted_payload.len()),
3932                    Ethernet2Header::LEN +
3933                    Ipv6Header::LEN +
3934                    icmp_expected.header_len() +
3935                    adapted_payload.len()
3936                );
3937
3938                // test builder.write()
3939                let mut buffer = Vec::<u8>::with_capacity(builder.size(adapted_payload.len()));
3940                builder.write(&mut buffer, adapted_payload).unwrap();
3941
3942                // decode packets
3943                let actual = PacketHeaders::from_ethernet_slice(&buffer).unwrap();
3944
3945                // check the packets could be decoded
3946                assert_eq!(
3947                    Some(LinkHeader::Ethernet2(Ethernet2Header{
3948                        source: [1,2,3,4,5,6],
3949                        destination: [7,8,9,10,11,12],
3950                        ether_type: ether_type::IPV6
3951                    })),
3952                    actual.link
3953                );
3954                assert_eq!(
3955                    Some(NetHeaders::Ipv6(ip_expected, Default::default())),
3956                    actual.net
3957                );
3958                assert_eq!(
3959                    Some(TransportHeader::Icmpv4(icmp_expected)),
3960                    actual.transport
3961                );
3962                assert_eq!(actual.payload.slice(), adapted_payload);
3963            };
3964
3965            // icmpv4
3966            {
3967                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3968                    .ipv6(ipv6_source, ipv6_dest, ipv6_hop_limit)
3969                    .icmpv4(icmpv4.clone());
3970
3971                test_builder(
3972                    builder,
3973                    icmpv4
3974                );
3975            }
3976
3977            // icmpv4_raw
3978            {
3979                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3980                    .ipv6(ipv6_source, ipv6_dest, ipv6_hop_limit)
3981                    .icmpv4_raw(icmpv4_type_u8, icmpv4_code_u8, icmpv4_bytes5to8);
3982
3983                test_builder(
3984                    builder,
3985                    Icmpv4Type::Unknown{
3986                        type_u8: icmpv4_type_u8,
3987                        code_u8: icmpv4_code_u8,
3988                        bytes5to8: icmpv4_bytes5to8,
3989                    }
3990                );
3991            }
3992
3993            // icmpv4_echo_request
3994            {
3995                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
3996                    .ipv6(ipv6_source, ipv6_dest, ipv6_hop_limit)
3997                    .icmpv4_echo_request(echo_id, echo_seq);
3998
3999                test_builder(
4000                    builder,
4001                    Icmpv4Type::EchoRequest(IcmpEchoHeader{
4002                        id: echo_id,
4003                        seq: echo_seq,
4004                    })
4005                );
4006            }
4007
4008            // icmp4_echo_reply
4009            {
4010                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
4011                    .ipv6(ipv6_source, ipv6_dest, ipv6_hop_limit)
4012                    .icmpv4_echo_reply(echo_id, echo_seq);
4013
4014                test_builder(
4015                    builder,
4016                    Icmpv4Type::EchoReply(IcmpEchoHeader{
4017                        id: echo_id,
4018                        seq: echo_seq,
4019                    })
4020                );
4021            }
4022        }
4023    }
4024
4025    proptest! {
4026        #[test]
4027        fn ipv6_icmpv6(
4028            ipv6_source in any::<[u8;16]>(),
4029            ipv6_dest in any::<[u8;16]>(),
4030            ipv6_hop_limit in any::<u8>(),
4031            icmpv6_type_u8 in 162u8..u8::MAX,
4032            icmpv6_code_u8 in any::<u8>(),
4033            icmpv6_bytes5to8 in any::<[u8;4]>(),
4034            icmpv6 in icmpv6_type_any(),
4035            echo_id in any::<u16>(),
4036            echo_seq in any::<u16>(),
4037            payload in proptest::collection::vec(any::<u8>(), 0..64),
4038        ) {
4039            let test_builder = |builder: PacketBuilderStep<Icmpv6Header>, icmpv6_type: Icmpv6Type| {
4040                let icmp_expected = Icmpv6Header::with_checksum(
4041                    icmpv6_type,
4042                    ipv6_source,
4043                    ipv6_dest,
4044                    &payload
4045                ).unwrap();
4046                let ip_expected = Ipv6Header{
4047                    traffic_class: 0,
4048                    flow_label: Ipv6FlowLabel::ZERO,
4049                    payload_length: (icmp_expected.header_len() + payload.len()) as u16,
4050                    next_header: ip_number::IPV6_ICMP,
4051                    hop_limit: ipv6_hop_limit,
4052                    source: ipv6_source,
4053                    destination: ipv6_dest
4054                };
4055
4056                // test builder.size()
4057                assert_eq!(
4058                    builder.size(payload.len()),
4059                    Ethernet2Header::LEN +
4060                    Ipv6Header::LEN +
4061                    icmp_expected.header_len() +
4062                    payload.len()
4063                );
4064
4065                // test builder.write()
4066                let mut buffer = Vec::<u8>::with_capacity(builder.size(payload.len()));
4067                builder.write(&mut buffer, &payload).unwrap();
4068
4069                // decode packets
4070                let actual = PacketHeaders::from_ethernet_slice(&buffer).unwrap();
4071
4072                // check the packets could be decoded
4073                assert_eq!(
4074                    Some(LinkHeader::Ethernet2(Ethernet2Header{
4075                        source: [1,2,3,4,5,6],
4076                        destination: [7,8,9,10,11,12],
4077                        ether_type: ether_type::IPV6
4078                    })),
4079                    actual.link
4080                );
4081                assert_eq!(
4082                    Some(NetHeaders::Ipv6(ip_expected, Default::default())),
4083                    actual.net
4084                );
4085                assert_eq!(
4086                    Some(TransportHeader::Icmpv6(icmp_expected)),
4087                    actual.transport
4088                );
4089                assert_eq!(actual.payload.slice(), &payload);
4090            };
4091
4092            // icmpv6
4093            {
4094                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
4095                    .ipv6(ipv6_source, ipv6_dest, ipv6_hop_limit)
4096                    .icmpv6(icmpv6.clone());
4097
4098                test_builder(
4099                    builder,
4100                    icmpv6
4101                );
4102            }
4103
4104            // icmpv6_raw
4105            {
4106                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
4107                    .ipv6(ipv6_source, ipv6_dest, ipv6_hop_limit)
4108                    .icmpv6_raw(icmpv6_type_u8, icmpv6_code_u8, icmpv6_bytes5to8);
4109
4110                test_builder(
4111                    builder,
4112                    Icmpv6Type::Unknown{
4113                        type_u8: icmpv6_type_u8,
4114                        code_u8: icmpv6_code_u8,
4115                        bytes5to8: icmpv6_bytes5to8,
4116                    }
4117                );
4118            }
4119
4120            // icmpv6_echo_request
4121            {
4122                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
4123                    .ipv6(ipv6_source, ipv6_dest, ipv6_hop_limit)
4124                    .icmpv6_echo_request(echo_id, echo_seq);
4125
4126                test_builder(
4127                    builder,
4128                    Icmpv6Type::EchoRequest(IcmpEchoHeader{
4129                        id: echo_id,
4130                        seq: echo_seq,
4131                    })
4132                );
4133            }
4134
4135            // icmp4_echo_reply
4136            {
4137                let builder = PacketBuilder::ethernet2([1,2,3,4,5,6],[7,8,9,10,11,12])
4138                    .ipv6(ipv6_source, ipv6_dest, ipv6_hop_limit)
4139                    .icmpv6_echo_reply(echo_id, echo_seq);
4140
4141                test_builder(
4142                    builder,
4143                    Icmpv6Type::EchoReply(IcmpEchoHeader{
4144                        id: echo_id,
4145                        seq: echo_seq,
4146                    })
4147                );
4148            }
4149        }
4150    }
4151}