1use crate::{
2 datalink::{
3 arp::ArpWriter,
4 ethernet::{
5 EthernetWriter, ETHERNET_MIN_HEADER_LENGTH, ETHERTYPE_QINQ, ETHERTYPE_VLAN,
6 VLAN_TAG_LENGTH,
7 },
8 },
9 network::{
10 checksum::pseudo_header,
11 extensions::{
12 authentication::AuthenticationHeaderWriter, fragment::FragmentHeaderWriter,
13 options::OptionsHeaderWriter, routing::RoutingHeaderWriter,
14 },
15 icmpv4::Icmpv4Writer,
16 icmpv6::Icmpv6Writer,
17 ipv4::IPv4Writer,
18 ipv6::IPv6Writer,
19 },
20 transport::{tcp::TcpWriter, udp::UdpWriter},
21};
22
23pub struct RawState;
30pub struct EthernetHeaderState;
31pub struct ArpHeaderState;
32pub struct Ipv4HeaderState;
33pub struct Ipv6HeaderState;
34pub struct TcpHeaderState;
35pub struct UdpHeaderState;
36pub struct Icmpv4HeaderState;
37pub struct Icmpv6HeaderState;
38pub struct Ipv4EncapsulatedState;
39pub struct Ipv6EncapsulatedState;
40pub struct HopByHopOptionsState;
41pub struct DestinationOptions1State;
42pub struct DestinationOptions2State;
43pub struct RoutingHeaderState;
44pub struct FragmentHeaderState;
45pub struct AuthHeaderState;
46
47pub struct PacketBuilder<'a, State> {
56 bytes: &'a mut [u8],
57 header_len: usize,
58 _state: State,
59}
60
61impl<'a, State> PacketBuilder<'a, State> {
63 #[inline]
65 pub fn header_len(&self) -> usize {
66 self.header_len
67 }
68
69 #[inline]
73 pub fn payload_len(&self) -> usize {
74 self.bytes.len() - self.header_len
75 }
76
77 #[inline]
81 pub fn payload(&self) -> &[u8] {
82 &self.bytes[self.header_len..]
83 }
84
85 #[inline]
87 pub fn build(self) -> &'a [u8] {
88 self.bytes
89 }
90}
91
92macro_rules! impl_raw {
95 ($state:ty) => {
96 impl<'a> PacketBuilder<'a, $state> {
97 #[inline]
98 pub fn new(bytes: &'a mut [u8]) -> PacketBuilder<'a, RawState> {
99 PacketBuilder {
100 bytes,
101 header_len: 0,
102 _state: RawState,
103 }
104 }
105 }
106 };
107}
108
109macro_rules! impl_ethernet {
110 ($state:ty) => {
111 impl<'a> PacketBuilder<'a, $state> {
112 #[inline]
113 pub fn ethernet(
114 mut self,
115 src_mac: &[u8; 6],
116 dest_mac: &[u8; 6],
117 ethertype: u16,
118 ) -> Result<PacketBuilder<'a, EthernetHeaderState>, &'static str> {
119 let mut writer = EthernetWriter::new(self.bytes)?;
120
121 writer.set_src_mac(src_mac);
122 writer.set_dest_mac(dest_mac);
123 writer.set_ethertype(ethertype);
124
125 self.header_len = ETHERNET_MIN_HEADER_LENGTH;
126
127 Ok(PacketBuilder {
128 bytes: self.bytes,
129 header_len: self.header_len,
130 _state: EthernetHeaderState,
131 })
132 }
133 }
134 };
135}
136
137macro_rules! impl_ethernet_vlan {
138 ($state:ty) => {
139 impl<'a> PacketBuilder<'a, $state> {
140 #[inline]
141 pub fn ethernet_vlan(
142 mut self,
143 src_mac: &[u8; 6],
144 dest_mac: &[u8; 6],
145 ethertype: u16,
146 tci: u16,
147 ) -> Result<PacketBuilder<'a, EthernetHeaderState>, &'static str> {
148 let mut writer = EthernetWriter::new(self.bytes)?;
149
150 writer.set_src_mac(src_mac);
151 writer.set_dest_mac(dest_mac);
152 writer.set_vlan_tag(ETHERTYPE_VLAN, tci)?;
153 writer.set_ethertype(ethertype);
154
155 self.header_len = ETHERNET_MIN_HEADER_LENGTH + VLAN_TAG_LENGTH;
156
157 Ok(PacketBuilder {
158 bytes: self.bytes,
159 header_len: self.header_len,
160 _state: EthernetHeaderState,
161 })
162 }
163 }
164 };
165}
166
167macro_rules! impl_ethernet_qinq {
168 ($state:ty) => {
169 impl<'a> PacketBuilder<'a, $state> {
170 #[inline]
171 pub fn ethernet_qinq(
172 mut self,
173 src_mac: &[u8; 6],
174 dest_mac: &[u8; 6],
175 ethertype: u16,
176 tci1: u16,
177 tci2: u16,
178 ) -> Result<PacketBuilder<'a, EthernetHeaderState>, &'static str> {
179 let mut writer = EthernetWriter::new(self.bytes)?;
180
181 writer.set_src_mac(src_mac);
182 writer.set_dest_mac(dest_mac);
183 writer.set_double_vlan_tag(ETHERTYPE_QINQ, tci1, ETHERTYPE_VLAN, tci2)?;
184 writer.set_ethertype(ethertype);
185
186 self.header_len = ETHERNET_MIN_HEADER_LENGTH + 2 * VLAN_TAG_LENGTH;
187
188 Ok(PacketBuilder {
189 bytes: self.bytes,
190 header_len: self.header_len,
191 _state: EthernetHeaderState,
192 })
193 }
194 }
195 };
196}
197
198macro_rules! impl_arp {
199 ($state:ty) => {
200 impl<'a> PacketBuilder<'a, $state> {
201 #[inline]
202 #[allow(clippy::too_many_arguments)]
203 pub fn arp(
204 mut self,
205 hardware_type: u16,
206 protocol_type: u16,
207 hardware_address_length: u8,
208 protocol_address_length: u8,
209 operation: u16,
210 src_mac: &[u8; 6],
211 src_ip: &[u8; 4],
212 dest_mac: &[u8; 6],
213 dest_ip: &[u8; 4],
214 ) -> Result<PacketBuilder<'a, ArpHeaderState>, &'static str> {
215 if self.bytes.len() < self.header_len {
216 return Err("Data too short to contain an ARP header.");
217 }
218
219 let mut writer = ArpWriter::new(&mut self.bytes[self.header_len..])?;
220
221 writer.set_htype(hardware_type);
222 writer.set_ptype(protocol_type);
223 writer.set_hlen(hardware_address_length);
224 writer.set_plen(protocol_address_length);
225 writer.set_oper(operation);
226 writer.set_sha(src_mac);
227 writer.set_spa(src_ip);
228 writer.set_tha(dest_mac);
229 writer.set_tpa(dest_ip);
230
231 self.header_len += writer.header_len();
232
233 Ok(PacketBuilder {
234 bytes: self.bytes,
235 header_len: self.header_len,
236 _state: ArpHeaderState,
237 })
238 }
239 }
240 };
241}
242
243macro_rules! impl_ipv4 {
244 ($state:ty) => {
245 impl<'a> PacketBuilder<'a, $state> {
246 #[inline]
247 #[allow(clippy::too_many_arguments)]
248 pub fn ipv4(
249 mut self,
250 version: u8,
251 ihl: u8,
252 dscp: u8,
253 ecn: u8,
254 total_length: u16,
255 identification: u16,
256 flags: u8,
257 fragment_offset: u16,
258 ttl: u8,
259 protocol: u8,
260 src_ip: &[u8; 4],
261 dest_ip: &[u8; 4],
262 ) -> Result<PacketBuilder<'a, Ipv4HeaderState>, &'static str> {
263 if self.bytes.len() < self.header_len {
264 return Err("Data too short to contain an IPv4 header.");
265 }
266
267 let mut writer = IPv4Writer::new(&mut self.bytes[self.header_len..])?;
268
269 writer.set_version(version);
270 writer.set_ihl(ihl);
271 writer.set_dscp(dscp);
272 writer.set_ecn(ecn);
273 writer.set_total_length(total_length);
274 writer.set_id(identification);
275 writer.set_flags(flags);
276 writer.set_fragment_offset(fragment_offset);
277 writer.set_ttl(ttl);
278 writer.set_protocol(protocol);
279 writer.set_src_ip(src_ip);
280 writer.set_dest_ip(dest_ip);
281 writer.set_checksum();
282
283 self.header_len += writer.header_len();
284
285 Ok(PacketBuilder {
286 bytes: self.bytes,
287 header_len: self.header_len,
288 _state: Ipv4HeaderState,
289 })
290 }
291 }
292 };
293}
294
295macro_rules! impl_ipv6 {
296 ($state:ty) => {
297 impl<'a> PacketBuilder<'a, $state> {
298 #[inline]
299 #[allow(clippy::too_many_arguments)]
300 pub fn ipv6(
301 mut self,
302 version: u8,
303 traffic_class: u8,
304 flow_label: u32,
305 payload_length: u16,
306 next_header: u8,
307 hop_limit: u8,
308 src_addr: &[u8; 16],
309 dest_addr: &[u8; 16],
310 ) -> Result<PacketBuilder<'a, Ipv6HeaderState>, &'static str> {
311 if self.bytes.len() < self.header_len {
312 return Err("Data too short to contain an IPv6 header.");
313 }
314
315 let mut writer = IPv6Writer::new(&mut self.bytes[self.header_len..])?;
316
317 writer.set_version(version);
318 writer.set_traffic_class(traffic_class);
319 writer.set_flow_label(flow_label);
320 writer.set_payload_length(payload_length);
321 writer.set_next_header(next_header);
322 writer.set_hop_limit(hop_limit);
323 writer.set_src_addr(src_addr);
324 writer.set_dest_addr(dest_addr);
325
326 self.header_len += writer.header_len();
327
328 Ok(PacketBuilder {
329 bytes: self.bytes,
330 header_len: self.header_len,
331 _state: Ipv6HeaderState,
332 })
333 }
334 }
335 };
336}
337
338macro_rules! impl_ipv4_encapsulated {
339 ($state:ty) => {
340 impl<'a> PacketBuilder<'a, $state> {
341 #[inline]
342 #[allow(clippy::too_many_arguments)]
343 pub fn ipv4(
344 mut self,
345 version: u8,
346 ihl: u8,
347 dscp: u8,
348 ecn: u8,
349 total_length: u16,
350 identification: u16,
351 flags: u8,
352 fragment_offset: u16,
353 ttl: u8,
354 protocol: u8,
355 src_ip: &[u8; 4],
356 dest_ip: &[u8; 4],
357 ) -> Result<PacketBuilder<'a, Ipv4EncapsulatedState>, &'static str> {
358 if self.bytes.len() < self.header_len {
359 return Err("Data too short to contain an IPv4 header.");
360 }
361
362 let mut writer = IPv4Writer::new(&mut self.bytes[self.header_len..])?;
363
364 writer.set_version(version);
365 writer.set_ihl(ihl);
366 writer.set_dscp(dscp);
367 writer.set_ecn(ecn);
368 writer.set_total_length(total_length);
369 writer.set_id(identification);
370 writer.set_flags(flags);
371 writer.set_fragment_offset(fragment_offset);
372 writer.set_ttl(ttl);
373 writer.set_protocol(protocol);
374 writer.set_src_ip(src_ip);
375 writer.set_dest_ip(dest_ip);
376 writer.set_checksum();
377
378 self.header_len += writer.header_len();
379
380 Ok(PacketBuilder {
381 bytes: self.bytes,
382 header_len: self.header_len,
383 _state: Ipv4EncapsulatedState,
384 })
385 }
386 }
387 };
388}
389
390macro_rules! impl_ipv6_encapsulated {
391 ($state:ty) => {
392 impl<'a> PacketBuilder<'a, $state> {
393 #[inline]
394 #[allow(clippy::too_many_arguments)]
395 pub fn ipv6(
396 mut self,
397 version: u8,
398 traffic_class: u8,
399 flow_label: u32,
400 payload_length: u16,
401 next_header: u8,
402 hop_limit: u8,
403 src_addr: &[u8; 16],
404 dest_addr: &[u8; 16],
405 ) -> Result<PacketBuilder<'a, Ipv6EncapsulatedState>, &'static str> {
406 if self.bytes.len() < self.header_len {
407 return Err("Data too short to contain an IPv6 header.");
408 }
409
410 let mut writer = IPv6Writer::new(&mut self.bytes[self.header_len..])?;
411
412 writer.set_version(version);
413 writer.set_traffic_class(traffic_class);
414 writer.set_flow_label(flow_label);
415 writer.set_payload_length(payload_length);
416 writer.set_next_header(next_header);
417 writer.set_hop_limit(hop_limit);
418 writer.set_src_addr(src_addr);
419 writer.set_dest_addr(dest_addr);
420
421 self.header_len += writer.header_len();
422
423 Ok(PacketBuilder {
424 bytes: self.bytes,
425 header_len: self.header_len,
426 _state: Ipv6EncapsulatedState,
427 })
428 }
429 }
430 };
431}
432
433macro_rules! impl_tcp {
434 ($state:ty, $addr_type:ty) => {
435 impl<'a> PacketBuilder<'a, $state> {
436 #[allow(clippy::too_many_arguments)]
437 #[inline]
438 pub fn tcp(
439 mut self,
440 src_ip: $addr_type,
441 src_port: u16,
442 dest_ip: $addr_type,
443 dest_port: u16,
444 sequence_number: u32,
445 acknowledgment_number: u32,
446 data_offset: u8,
447 reserved: u8,
448 flags: u8,
449 window_size: u16,
450 urgent_pointer: u16,
451 payload: Option<&[u8]>,
452 ) -> Result<PacketBuilder<'a, TcpHeaderState>, &'static str> {
453 if self.bytes.len() < self.header_len {
454 return Err("Data too short to contain a TCP segment.");
455 }
456
457 let mut writer = TcpWriter::new(&mut self.bytes[self.header_len..])?;
458
459 writer.set_src_port(src_port);
460 writer.set_dest_port(dest_port);
461 writer.set_sequence_number(sequence_number);
462 writer.set_ack_number(acknowledgment_number);
463 writer.set_data_offset(data_offset);
464 writer.set_reserved(reserved);
465 writer.set_flags(flags);
466 writer.set_window_size(window_size);
467 writer.set_urgent_pointer(urgent_pointer);
468
469 if let Some(payload) = payload {
470 writer.set_payload(payload)?;
471 }
472
473 let pseudo_sum = pseudo_header(src_ip, dest_ip, 6, writer.packet_len());
474 writer.set_checksum(pseudo_sum);
475
476 self.header_len += writer.header_len();
477
478 Ok(PacketBuilder {
479 bytes: self.bytes,
480 header_len: self.header_len,
481 _state: TcpHeaderState,
482 })
483 }
484 }
485 };
486}
487
488macro_rules! impl_udp {
489 ($state:ty, $addr_type:ty) => {
490 impl<'a> PacketBuilder<'a, $state> {
491 #[inline]
492 pub fn udp(
493 mut self,
494 src_addr: $addr_type,
495 src_port: u16,
496 dest_addr: $addr_type,
497 dest_port: u16,
498 length: u16,
499 payload: Option<&[u8]>,
500 ) -> Result<PacketBuilder<'a, UdpHeaderState>, &'static str> {
501 if self.bytes.len() < self.header_len {
502 return Err("Data too short to contain a UDP datagram.");
503 }
504
505 let mut writer = UdpWriter::new(&mut self.bytes[self.header_len..])?;
506
507 writer.set_src_port(src_port);
508 writer.set_dest_port(dest_port);
509 writer.set_length(length);
510
511 if let Some(payload) = payload {
512 writer.set_payload(payload)?;
513 }
514
515 let pseudo_sum = pseudo_header(src_addr, dest_addr, 17, writer.packet_len());
516 writer.set_checksum(pseudo_sum);
517
518 self.header_len += writer.header_len();
519
520 Ok(PacketBuilder {
521 bytes: self.bytes,
522 header_len: self.header_len,
523 _state: UdpHeaderState,
524 })
525 }
526 }
527 };
528}
529
530macro_rules! impl_icmpv4 {
531 ($state:ty) => {
532 impl<'a> PacketBuilder<'a, $state> {
533 #[inline]
534 pub fn icmpv4(
535 mut self,
536 icmp_type: u8,
537 icmp_code: u8,
538 payload: Option<&[u8]>,
539 ) -> Result<PacketBuilder<'a, Icmpv4HeaderState>, &'static str> {
540 if self.bytes.len() < self.header_len {
541 return Err("Data too short to contain an ICMP packet.");
542 }
543
544 let mut writer = Icmpv4Writer::new(&mut self.bytes[self.header_len..])?;
545
546 writer.set_icmp_type(icmp_type);
547 writer.set_icmp_code(icmp_code);
548
549 if let Some(payload) = payload {
550 writer.set_payload(payload)?;
551 }
552
553 writer.set_checksum();
554
555 self.header_len += writer.header_len();
556
557 Ok(PacketBuilder {
558 bytes: self.bytes,
559 header_len: self.header_len,
560 _state: Icmpv4HeaderState,
561 })
562 }
563 }
564 };
565}
566
567macro_rules! impl_icmpv6 {
568 ($state:ty, $addr_type:ty) => {
569 impl<'a> PacketBuilder<'a, $state> {
570 #[inline]
571 pub fn icmpv6(
572 mut self,
573 src_addr: $addr_type,
574 dest_addr: $addr_type,
575 icmp_type: u8,
576 icmp_code: u8,
577 payload: Option<&[u8]>,
578 ) -> Result<PacketBuilder<'a, Icmpv6HeaderState>, &'static str> {
579 if self.bytes.len() < self.header_len {
580 return Err("Data too short to contain an ICMPv6 packet.");
581 }
582
583 let mut writer = Icmpv6Writer::new(&mut self.bytes[self.header_len..])?;
584
585 writer.set_icmp_type(icmp_type);
586 writer.set_icmp_code(icmp_code);
587
588 if let Some(payload) = payload {
589 writer.set_payload(payload)?;
590 }
591
592 let pseudo_sum = pseudo_header(src_addr, dest_addr, 58, writer.packet_len());
593 writer.set_checksum(pseudo_sum);
594
595 self.header_len += writer.header_len();
596
597 Ok(PacketBuilder {
598 bytes: self.bytes,
599 header_len: self.header_len,
600 _state: Icmpv6HeaderState,
601 })
602 }
603 }
604 };
605}
606
607macro_rules! impl_hop_by_hop {
608 ($state:ty) => {
609 impl<'a> PacketBuilder<'a, $state> {
610 #[inline]
611 pub fn hop_by_hop(
612 mut self,
613 next_header: u8,
614 extension_len: u8,
615 options: &[u8],
616 ) -> Result<PacketBuilder<'a, HopByHopOptionsState>, &'static str> {
617 if self.bytes.len() < self.header_len {
618 return Err("Data too short to contain an IPv6 Hop-by-Hop Options header.");
619 }
620
621 let mut writer = OptionsHeaderWriter::new(&mut self.bytes[self.header_len..])?;
622
623 writer.set_next_header(next_header);
624 writer.set_header_ext_len(extension_len);
625 writer.set_options(options)?;
626
627 self.header_len += writer.header_len();
628
629 Ok(PacketBuilder {
630 bytes: self.bytes,
631 header_len: self.header_len,
632 _state: HopByHopOptionsState,
633 })
634 }
635 }
636 };
637}
638
639macro_rules! impl_destination_options_1 {
640 ($state:ty) => {
641 impl<'a> PacketBuilder<'a, $state> {
642 #[inline]
643 pub fn destination_options1(
644 mut self,
645 next_header: u8,
646 extension_len: u8,
647 options: &[u8],
648 ) -> Result<PacketBuilder<'a, DestinationOptions1State>, &'static str> {
649 if self.bytes.len() < self.header_len {
650 return Err("Data too short to contain an IPv6 Destination Options header.");
651 }
652
653 let mut writer = OptionsHeaderWriter::new(&mut self.bytes[self.header_len..])?;
654
655 writer.set_next_header(next_header);
656 writer.set_header_ext_len(extension_len);
657 writer.set_options(options)?;
658
659 self.header_len += writer.header_len();
660
661 Ok(PacketBuilder {
662 bytes: self.bytes,
663 header_len: self.header_len,
664 _state: DestinationOptions1State,
665 })
666 }
667 }
668 };
669}
670
671macro_rules! impl_routing_header {
672 ($state:ty) => {
673 impl<'a> PacketBuilder<'a, $state> {
674 #[inline]
675 pub fn routing_header(
676 mut self,
677 next_header: u8,
678 header_ext_len: u8,
679 routing_type: u8,
680 segments_left: u8,
681 data: &[u8],
682 ) -> Result<PacketBuilder<'a, RoutingHeaderState>, &'static str> {
683 if self.bytes.len() < self.header_len {
684 return Err("Data too short to contain an IPv6 Routing header.");
685 }
686
687 let mut writer = RoutingHeaderWriter::new(&mut self.bytes[self.header_len..])?;
688
689 writer.set_next_header(next_header);
690 writer.set_header_ext_len(header_ext_len);
691 writer.set_routing_type(routing_type);
692 writer.set_segments_left(segments_left);
693 writer.set_data(data)?;
694
695 self.header_len += writer.header_len();
696
697 Ok(PacketBuilder {
698 bytes: self.bytes,
699 header_len: self.header_len,
700 _state: RoutingHeaderState,
701 })
702 }
703 }
704 };
705}
706
707macro_rules! impl_fragment_header {
708 ($state:ty) => {
709 impl<'a> PacketBuilder<'a, $state> {
710 #[inline]
711 pub fn fragment_header(
712 mut self,
713 next_header: u8,
714 fragment_offset: u16,
715 m_flag: bool,
716 identification: u32,
717 ) -> Result<PacketBuilder<'a, FragmentHeaderState>, &'static str> {
718 if self.bytes.len() < self.header_len {
719 return Err("Data too short to contain an IPv6 Routing header.");
720 }
721
722 let mut writer = FragmentHeaderWriter::new(&mut self.bytes[self.header_len..])?;
723
724 writer.set_next_header(next_header);
725 writer.set_reserved(0);
726 writer.set_fragment_offset(fragment_offset);
727 writer.set_res(0);
728 writer.set_m_flag(m_flag);
729 writer.set_identification(identification);
730
731 self.header_len += writer.header_len();
732
733 Ok(PacketBuilder {
734 bytes: self.bytes,
735 header_len: self.header_len,
736 _state: FragmentHeaderState,
737 })
738 }
739 }
740 };
741}
742
743macro_rules! impl_authentication_header {
744 ($state:ty) => {
745 impl<'a> PacketBuilder<'a, $state> {
746 #[inline]
747 pub fn authentication_header(
748 mut self,
749 next_header: u8,
750 payload_len: u8,
751 spi: u32,
752 seq_num: u32,
753 auth_data: &[u8],
754 ) -> Result<PacketBuilder<'a, AuthHeaderState>, &'static str> {
755 if self.bytes.len() < self.header_len {
756 return Err("Data too short to contain an IPv6 Authentication header.");
757 }
758
759 let mut writer =
760 AuthenticationHeaderWriter::new(&mut self.bytes[self.header_len..])?;
761
762 writer.set_next_header(next_header);
763 writer.set_payload_len(payload_len);
764 writer.set_reserved(0);
765 writer.set_spi(spi);
766 writer.set_sequence_number(seq_num);
767 writer.set_authentication_data(auth_data)?;
768
769 self.header_len += writer.header_len();
770
771 Ok(PacketBuilder {
772 bytes: self.bytes,
773 header_len: self.header_len,
774 _state: AuthHeaderState,
775 })
776 }
777 }
778 };
779}
780
781macro_rules! impl_destination_options_2 {
782 ($state:ty) => {
783 impl<'a> PacketBuilder<'a, $state> {
784 #[inline]
785 pub fn destination_options2(
786 mut self,
787 next_header: u8,
788 extension_len: u8,
789 options: &[u8],
790 ) -> Result<PacketBuilder<'a, DestinationOptions2State>, &'static str> {
791 if self.bytes.len() < self.header_len {
792 return Err("Data too short to contain an IPv6 Destination Options header.");
793 }
794
795 let mut writer = OptionsHeaderWriter::new(&mut self.bytes[self.header_len..])?;
796
797 writer.set_next_header(next_header);
798 writer.set_header_ext_len(extension_len);
799 writer.set_options(options)?;
800
801 self.header_len += writer.header_len();
802
803 Ok(PacketBuilder {
804 bytes: self.bytes,
805 header_len: self.header_len,
806 _state: DestinationOptions2State,
807 })
808 }
809 }
810 };
811}
812
813impl_raw!(RawState);
818impl_ethernet!(RawState);
819impl_ethernet_vlan!(RawState);
820impl_ethernet_qinq!(RawState);
821
822impl_arp!(EthernetHeaderState);
824impl_ipv4!(EthernetHeaderState);
825impl_ipv6!(EthernetHeaderState);
826
827impl_tcp!(Ipv4EncapsulatedState, &[u8; 4]);
829impl_udp!(Ipv4EncapsulatedState, &[u8; 4]);
830impl_icmpv4!(Ipv4EncapsulatedState);
831
832impl_tcp!(Ipv6EncapsulatedState, &[u8; 16]);
834impl_udp!(Ipv6EncapsulatedState, &[u8; 16]);
835impl_icmpv6!(Ipv6EncapsulatedState, &[u8; 16]);
836
837impl_tcp!(Ipv4HeaderState, &[u8; 4]);
839impl_udp!(Ipv4HeaderState, &[u8; 4]);
840impl_icmpv4!(Ipv4HeaderState);
841impl_ipv4_encapsulated!(Ipv4HeaderState);
842impl_ipv6_encapsulated!(Ipv4HeaderState);
843
844impl_tcp!(Ipv6HeaderState, &[u8; 16]);
846impl_udp!(Ipv6HeaderState, &[u8; 16]);
847impl_icmpv6!(Ipv6HeaderState, &[u8; 16]);
848impl_ipv4_encapsulated!(Ipv6HeaderState);
849impl_ipv6_encapsulated!(Ipv6HeaderState);
850impl_hop_by_hop!(Ipv6HeaderState);
851impl_destination_options_1!(Ipv6HeaderState);
852impl_routing_header!(Ipv6HeaderState);
853impl_fragment_header!(Ipv6HeaderState);
854impl_authentication_header!(Ipv6HeaderState);
855impl_destination_options_2!(Ipv6HeaderState);
856
857impl_tcp!(HopByHopOptionsState, &[u8; 16]);
859impl_udp!(HopByHopOptionsState, &[u8; 16]);
860impl_icmpv6!(HopByHopOptionsState, &[u8; 16]);
861impl_ipv4_encapsulated!(HopByHopOptionsState);
862impl_ipv6_encapsulated!(HopByHopOptionsState);
863impl_destination_options_1!(HopByHopOptionsState);
864impl_routing_header!(HopByHopOptionsState);
865impl_fragment_header!(HopByHopOptionsState);
866impl_authentication_header!(HopByHopOptionsState);
867impl_destination_options_2!(HopByHopOptionsState);
868
869impl_tcp!(DestinationOptions1State, &[u8; 16]);
871impl_udp!(DestinationOptions1State, &[u8; 16]);
872impl_icmpv6!(DestinationOptions1State, &[u8; 16]);
873impl_ipv4_encapsulated!(DestinationOptions1State);
874impl_ipv6_encapsulated!(DestinationOptions1State);
875impl_routing_header!(DestinationOptions1State);
876
877impl_tcp!(RoutingHeaderState, &[u8; 16]);
879impl_udp!(RoutingHeaderState, &[u8; 16]);
880impl_icmpv6!(RoutingHeaderState, &[u8; 16]);
881impl_ipv4_encapsulated!(RoutingHeaderState);
882impl_ipv6_encapsulated!(RoutingHeaderState);
883impl_fragment_header!(RoutingHeaderState);
884impl_authentication_header!(RoutingHeaderState);
885impl_destination_options_2!(RoutingHeaderState);
886
887impl_tcp!(FragmentHeaderState, &[u8; 16]);
889impl_udp!(FragmentHeaderState, &[u8; 16]);
890impl_icmpv6!(FragmentHeaderState, &[u8; 16]);
891impl_ipv4_encapsulated!(FragmentHeaderState);
892impl_ipv6_encapsulated!(FragmentHeaderState);
893impl_authentication_header!(FragmentHeaderState);
894impl_destination_options_2!(FragmentHeaderState);
895
896impl_tcp!(AuthHeaderState, &[u8; 16]);
898impl_udp!(AuthHeaderState, &[u8; 16]);
899impl_icmpv6!(AuthHeaderState, &[u8; 16]);
900impl_ipv4_encapsulated!(AuthHeaderState);
901impl_ipv6_encapsulated!(AuthHeaderState);
902impl_destination_options_2!(AuthHeaderState);
903
904impl_tcp!(DestinationOptions2State, &[u8; 16]);
906impl_udp!(DestinationOptions2State, &[u8; 16]);
907impl_icmpv6!(DestinationOptions2State, &[u8; 16]);
908impl_ipv4_encapsulated!(DestinationOptions2State);
909impl_ipv6_encapsulated!(DestinationOptions2State);
910
911#[cfg(test)]
912mod tests {
913 use super::*;
914 use crate::{
915 datalink::arp::ARP_HEADER_LENGTH, misc::IpInIp, network::ipv4::IPV4_MIN_HEADER_LENGTH,
916 packet::parser::PacketParser, transport::udp::UDP_HEADER_LENGTH,
917 };
918
919 #[test]
920 fn write_payload() {
921 let mut buffer = [0u8; 64];
923
924 let payload = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
925
926 let packet_builder = PacketBuilder::new(&mut buffer)
928 .ethernet(&[1, 2, 3, 4, 5, 6], &[7, 8, 9, 10, 11, 12], 0x0800)
930 .unwrap()
931 .ipv4(
933 4,
934 5,
935 0,
936 0,
937 50,
938 0,
939 0,
940 0,
941 64,
942 17,
943 &[192, 168, 1, 1],
944 &[192, 168, 1, 2],
945 )
946 .unwrap()
947 .udp(
949 &[192, 168, 1, 1],
950 12345,
951 &[192, 168, 1, 2],
952 54321,
953 30,
954 Some(&payload),
955 )
956 .unwrap();
957
958 assert_eq!(
960 packet_builder.header_len(),
961 ETHERNET_MIN_HEADER_LENGTH + IPV4_MIN_HEADER_LENGTH + UDP_HEADER_LENGTH
962 );
963
964 assert_eq!(
966 packet_builder.payload(),
967 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
968 );
969
970 let packet = packet_builder.build();
972
973 let parser = PacketParser::parse(&packet);
975
976 assert!(parser.is_ok());
978
979 let parser = parser.unwrap();
981
982 assert!(parser.udp.is_some());
984
985 let udp = parser.udp.unwrap();
987
988 assert_eq!(
990 udp.payload(),
991 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
992 );
993 }
994
995 #[test]
996 fn misc() {
997 let mut packet = [0u8; 64];
999
1000 let allocations = allocation_counter::measure(|| {
1002 let packet_builder = PacketBuilder::new(&mut packet);
1004
1005 let eth_builder = packet_builder
1007 .ethernet(
1008 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1009 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
1010 2054,
1011 )
1012 .unwrap();
1013
1014 assert_eq!(eth_builder.header_len(), ETHERNET_MIN_HEADER_LENGTH);
1016
1017 let arp_builder = eth_builder
1019 .arp(
1020 1,
1021 2048,
1022 6,
1023 4,
1024 1,
1025 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1026 &[192, 168, 1, 1],
1027 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
1028 &[192, 168, 1, 2],
1029 )
1030 .unwrap();
1031
1032 assert_eq!(
1034 arp_builder.header_len(),
1035 ETHERNET_MIN_HEADER_LENGTH + ARP_HEADER_LENGTH
1036 );
1037
1038 assert_eq!(arp_builder.payload_len(), 22);
1040 });
1041
1042 assert_eq!(allocations.count_total, 0);
1044 }
1045
1046 #[test]
1047 fn arp_in_ethernet() {
1048 let mut packet = [0u8; 42];
1050
1051 let should_be = [
1053 255, 255, 255, 255, 255, 255, 52, 151, 246, 148, 2, 15, 8, 6, 0, 1, 8, 0, 6, 4, 0, 1,
1054 52, 151, 246, 148, 2, 15, 192, 168, 1, 1, 0, 0, 0, 0, 0, 0, 192, 168, 1, 2,
1055 ];
1056
1057 let allocations = allocation_counter::measure(|| {
1059 let packet_builder = PacketBuilder::new(&mut packet);
1061
1062 packet_builder
1064 .ethernet(
1065 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1066 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
1067 2054,
1068 )
1069 .unwrap()
1070 .arp(
1071 1,
1072 2048,
1073 6,
1074 4,
1075 1,
1076 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1077 &[192, 168, 1, 1],
1078 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
1079 &[192, 168, 1, 2],
1080 )
1081 .unwrap();
1082 });
1083
1084 assert_eq!(packet, should_be);
1086
1087 assert_eq!(allocations.count_total, 0);
1089 }
1090
1091 #[test]
1092 fn tcp_in_ipv4_in_ethernet() {
1093 let mut packet = [0u8; 54];
1095
1096 let should_be = [
1098 4, 180, 254, 154, 129, 199, 52, 151, 246, 148, 2, 15, 8, 0, 53, 143, 48, 57, 212, 49,
1099 112, 57, 123, 6, 87, 113, 192, 168, 1, 1, 192, 168, 1, 2, 0, 99, 0, 11, 0, 0, 0, 123,
1100 0, 0, 1, 65, 179, 99, 16, 225, 177, 80, 4, 210,
1101 ];
1102
1103 let allocations = allocation_counter::measure(|| {
1105 let packet_builder = PacketBuilder::new(&mut packet);
1107
1108 packet_builder
1110 .ethernet(
1111 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1112 &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1113 2048,
1114 )
1115 .unwrap()
1116 .ipv4(
1117 99,
1118 5,
1119 99,
1120 123,
1121 12345,
1122 54321,
1123 99,
1124 12345,
1125 123,
1126 6,
1127 &[192, 168, 1, 1],
1128 &[192, 168, 1, 2],
1129 )
1130 .unwrap()
1131 .tcp(
1132 &[192, 168, 1, 1],
1133 99,
1134 &[192, 168, 1, 2],
1135 11,
1136 123,
1137 321,
1138 11,
1139 99,
1140 99,
1141 4321,
1142 1234,
1143 None,
1144 )
1145 .unwrap();
1146 });
1147
1148 assert_eq!(packet, should_be);
1150
1151 assert_eq!(allocations.count_total, 0);
1153 }
1154
1155 #[test]
1156 fn udp_in_ipv4_in_ethernet() {
1157 let mut packet = [0u8; 54];
1159
1160 let should_be = [
1162 4, 180, 254, 154, 129, 199, 52, 151, 246, 148, 2, 15, 8, 0, 53, 143, 48, 57, 212, 49,
1163 112, 57, 123, 6, 87, 113, 192, 168, 1, 1, 192, 168, 1, 2, 0, 99, 0, 11, 16, 225, 107,
1164 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1165 ];
1166
1167 let allocations = allocation_counter::measure(|| {
1169 let packet_builder = PacketBuilder::new(&mut packet);
1171
1172 packet_builder
1174 .ethernet(
1175 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1176 &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1177 2048,
1178 )
1179 .unwrap()
1180 .ipv4(
1181 99,
1182 5,
1183 99,
1184 123,
1185 12345,
1186 54321,
1187 99,
1188 12345,
1189 123,
1190 6,
1191 &[192, 168, 1, 1],
1192 &[192, 168, 1, 2],
1193 )
1194 .unwrap()
1195 .udp(&[192, 168, 1, 1], 99, &[192, 168, 1, 2], 11, 4321, None)
1196 .unwrap();
1197 });
1198
1199 assert_eq!(packet, should_be);
1201
1202 assert_eq!(allocations.count_total, 0);
1204 }
1205
1206 #[test]
1207 fn icmpv4_in_ipv4_in_ethernet() {
1208 let mut packet = [0u8; 64];
1210
1211 let should_be = [
1213 4, 180, 254, 154, 129, 199, 52, 151, 246, 148, 2, 15, 8, 0, 69, 143, 48, 57, 212, 49,
1214 112, 57, 123, 1, 71, 118, 192, 168, 1, 1, 192, 168, 1, 2, 8, 0, 247, 255, 0, 0, 0, 0,
1215 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1216 ];
1217
1218 let allocations = allocation_counter::measure(|| {
1220 let packet_builder = PacketBuilder::new(&mut packet);
1222
1223 packet_builder
1225 .ethernet(
1226 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1227 &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1228 2048,
1229 )
1230 .unwrap()
1231 .ipv4(
1232 4,
1233 5,
1234 99,
1235 123,
1236 12345,
1237 54321,
1238 99,
1239 12345,
1240 123,
1241 1,
1242 &[192, 168, 1, 1],
1243 &[192, 168, 1, 2],
1244 )
1245 .unwrap()
1246 .icmpv4(8, 0, None)
1247 .unwrap();
1248 });
1249
1250 assert_eq!(packet, should_be);
1252
1253 assert_eq!(allocations.count_total, 0);
1255 }
1256
1257 #[test]
1258 fn build_parse_ipv6() {
1259 let src_addr = [
1261 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70,
1262 0x73, 0x34,
1263 ];
1264
1265 let dest_addr = [
1267 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0xb3, 0xff, 0xfe, 0x1e,
1268 0x83, 0x29,
1269 ];
1270
1271 let mut buffer = [0u8; 64];
1273
1274 let packet = PacketBuilder::new(&mut buffer)
1276 .ethernet(
1277 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1278 &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1279 34525,
1280 )
1281 .unwrap()
1282 .ipv6(6, 5, 4, 31, 17, 10, &src_addr, &dest_addr)
1283 .unwrap()
1284 .udp(&src_addr, 99, &dest_addr, 80, 10, None)
1285 .unwrap()
1286 .build();
1287
1288 assert_eq!(
1290 packet,
1291 [
1292 4, 180, 254, 154, 129, 199, 52, 151, 246, 148, 2, 15, 134, 221, 96, 80, 0, 4, 0,
1293 31, 17, 10, 32, 1, 13, 184, 133, 163, 0, 0, 0, 0, 138, 46, 3, 112, 115, 52, 254,
1294 128, 0, 0, 0, 0, 0, 0, 2, 2, 179, 255, 254, 30, 131, 41, 0, 99, 0, 80, 0, 10, 21,
1295 45, 0, 0
1296 ]
1297 );
1298
1299 let parser = PacketParser::parse(&packet);
1301
1302 assert!(parser.is_ok());
1304
1305 let unwrapped = parser.unwrap();
1307
1308 assert!(unwrapped.ethernet.is_some());
1310 assert!(unwrapped.ipv6.is_some());
1311 assert!(unwrapped.udp.is_some());
1312
1313 assert!(unwrapped.arp.is_none());
1315 assert!(unwrapped.icmpv4.is_none());
1316 assert!(unwrapped.tcp.is_none());
1317 }
1318
1319 #[test]
1320 fn build_parse_qinq() {
1321 let mut buffer = [0u8; 64];
1323
1324 let packet = PacketBuilder::new(&mut buffer)
1326 .ethernet_qinq(
1328 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1329 &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1330 2048,
1331 200,
1332 100,
1333 )
1334 .unwrap()
1335 .ipv4(
1337 4,
1338 5,
1339 99,
1340 123,
1341 42,
1342 54321,
1343 99,
1344 12345,
1345 123,
1346 17,
1347 &[192, 168, 1, 1],
1348 &[192, 168, 1, 2],
1349 )
1350 .unwrap()
1351 .udp(&[192, 168, 1, 1], 99, &[192, 168, 1, 2], 11, 22, None)
1353 .unwrap()
1354 .build();
1355
1356 let parser = PacketParser::parse(&packet);
1358
1359 assert!(parser.is_ok());
1361
1362 let unwrapped = parser.unwrap();
1364
1365 assert!(unwrapped.ethernet.is_some());
1367 assert!(unwrapped.ipv4.is_some());
1368 assert!(unwrapped.udp.is_some());
1369
1370 assert!(unwrapped.arp.is_none());
1372 assert!(unwrapped.icmpv4.is_none());
1373 assert!(unwrapped.tcp.is_none());
1374
1375 let ethernet = unwrapped.ethernet.unwrap();
1377
1378 assert!(ethernet.vlan_tag().is_none());
1380 assert!(ethernet.double_vlan_tag().is_some());
1381
1382 assert_eq!(ethernet.src_mac(), [0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f]);
1384 assert_eq!(ethernet.dest_mac(), [0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7]);
1385 assert_eq!(ethernet.ethertype(), 2048);
1386 assert_eq!(
1387 ethernet.double_vlan_tag().unwrap(),
1388 ((ETHERTYPE_QINQ, 200), (ETHERTYPE_VLAN, 100))
1389 );
1390 }
1391
1392 #[test]
1393 fn build_parse_qinq_icmpv6() {
1394 let mut buffer = [0u8; 70];
1396
1397 let src_addr = [
1399 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70,
1400 0x73, 0x34,
1401 ];
1402
1403 let dest_addr = [
1405 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0xb3, 0xff, 0xfe, 0x1e,
1406 0x83, 0x29,
1407 ];
1408
1409 let packet = PacketBuilder::new(&mut buffer)
1411 .ethernet_qinq(
1413 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1414 &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1415 34525,
1416 200,
1417 100,
1418 )
1419 .unwrap()
1420 .ipv6(6, 5, 4, 3, 58, 255, &src_addr, &dest_addr)
1422 .unwrap()
1423 .icmpv6(&src_addr, &dest_addr, 128, 0, None)
1425 .unwrap()
1426 .build();
1427
1428 let parser = PacketParser::parse(&packet);
1430
1431 assert!(parser.is_ok());
1433
1434 let unwrapped = parser.unwrap();
1436
1437 assert!(unwrapped.ethernet.is_some());
1439 assert!(unwrapped.ipv6.is_some());
1440 assert!(unwrapped.icmpv6.is_some());
1441
1442 assert!(unwrapped.arp.is_none());
1444 assert!(unwrapped.udp.is_none());
1445 assert!(unwrapped.tcp.is_none());
1446 assert!(unwrapped.icmpv4.is_none());
1447 }
1448
1449 #[test]
1450 pub fn build_parse_very_complex_packet() {
1451 let mut buffer = [0u8; 300];
1453
1454 let packet = PacketBuilder::new(&mut buffer)
1456 .ethernet_qinq(
1457 &[0x34, 0x97, 0xf6, 0x94, 0x02, 0x0f],
1458 &[0x04, 0xb4, 0xfe, 0x9a, 0x81, 0xc7],
1459 34525,
1460 200,
1461 100,
1462 )
1463 .unwrap()
1464 .ipv6(6, 5, 4, 3, 0, 255, &[0; 16], &[0; 16])
1465 .unwrap()
1466 .hop_by_hop(60, 1, &[1; 8])
1467 .unwrap()
1468 .destination_options1(43, 1, &[1; 8])
1469 .unwrap()
1470 .routing_header(44, 1, 2, 3, &[2; 8])
1471 .unwrap()
1472 .fragment_header(51, 255, true, 0x04050607)
1473 .unwrap()
1474 .authentication_header(60, 2, 305419896, 2271560481, &[1; 8])
1475 .unwrap()
1476 .destination_options2(4, 1, &[1; 8])
1477 .unwrap()
1478 .ipv4(
1479 4,
1480 5,
1481 0,
1482 0,
1483 150,
1484 0,
1485 0,
1486 0,
1487 64,
1488 6,
1489 &[192, 168, 1, 1],
1490 &[192, 168, 1, 2],
1491 )
1492 .unwrap()
1493 .tcp(
1494 &[192, 168, 1, 1],
1495 99,
1496 &[192, 168, 1, 2],
1497 11,
1498 123,
1499 321,
1500 11,
1501 99,
1502 99,
1503 4321,
1504 1234,
1505 Some(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
1506 )
1507 .unwrap()
1508 .build();
1509
1510 let parser = PacketParser::parse(&packet);
1512
1513 assert!(parser.is_ok());
1515
1516 let unwrapped = parser.unwrap();
1518
1519 assert!(unwrapped.ethernet.is_some());
1521 assert!(unwrapped.ipv6.is_some());
1522 assert!(unwrapped.ip_in_ip.is_some());
1523 assert!(unwrapped.tcp.is_some());
1524
1525 assert!(unwrapped.arp.is_none());
1527 assert!(unwrapped.udp.is_none());
1528 assert!(unwrapped.icmpv4.is_none());
1529 assert!(unwrapped.icmpv6.is_none());
1530
1531 let ipv6 = unwrapped.ipv6.unwrap();
1533
1534 assert!(ipv6.extension_headers.is_some());
1536
1537 let extensions = ipv6.extension_headers.unwrap();
1539
1540 assert!(extensions.hop_by_hop.is_some());
1542 assert!(extensions.destination_1st.is_some());
1543 assert!(extensions.routing.is_some());
1544 assert!(extensions.fragment.is_some());
1545 assert!(extensions.auth_header.is_some());
1546 assert!(extensions.destination_2nd.is_some());
1547
1548 let ip_in_ip = unwrapped.ip_in_ip.unwrap();
1550
1551 assert!(match ip_in_ip {
1553 IpInIp::Ipv4(_) => true,
1554 _ => false,
1555 });
1556 }
1557}