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