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