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