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