1use core::any::Any;
4use core::fmt;
5use core::net::{Ipv4Addr, Ipv6Addr};
6use core::ops::Div;
7
8use crate::checksum::{ipv4_pseudo_header_checksum, ipv6_pseudo_header_checksum};
9use crate::error::Result;
10use crate::protocols::icmp::{Icmpv4, Icmpv4QuotedIp, Icmpv6, NeighborSolicitation};
11use crate::protocols::igmp::Igmp;
12use crate::protocols::ip::{v4::Ipv4, v6::Ipv6};
13use crate::protocols::link::{Arp, Ethernet, Vlan};
14use crate::protocols::transport::{Tcp, Udp};
15use crate::registry::ProtocolRegistry;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19pub enum TransportChecksumContext {
20 Ipv4 {
22 source: Ipv4Addr,
24 destination: Ipv4Addr,
26 protocol: u8,
28 },
29 Ipv6 {
31 source: Ipv6Addr,
33 destination: Ipv6Addr,
35 next_header: u8,
37 },
38}
39
40impl TransportChecksumContext {
41 pub fn checksum(self, transport: &[u8]) -> u16 {
43 match self {
44 Self::Ipv4 {
45 source,
46 destination,
47 protocol,
48 } => ipv4_pseudo_header_checksum(source, destination, protocol, transport),
49 Self::Ipv6 {
50 source,
51 destination,
52 next_header,
53 } => ipv6_pseudo_header_checksum(source, destination, next_header, transport),
54 }
55 }
56}
57
58pub trait Layer: fmt::Debug + Send + Sync + 'static {
64 fn name(&self) -> &'static str;
66
67 fn summary(&self) -> String {
69 self.name().to_string()
70 }
71
72 fn inspection_fields(&self) -> Vec<(&'static str, String)> {
74 Vec::new()
75 }
76
77 fn encoded_len(&self) -> usize;
79
80 fn encoded_len_with_context(&self, _ctx: &LayerContext<'_>) -> usize {
88 self.encoded_len()
89 }
90
91 fn compile(&self, ctx: &LayerContext<'_>, out: &mut Vec<u8>) -> Result<()>;
93
94 fn consumes_following(&self) -> bool {
104 false
105 }
106
107 fn transport_checksum_context(
109 &self,
110 _transport_protocol: u8,
111 ) -> Option<TransportChecksumContext> {
112 None
113 }
114
115 fn clone_layer(&self) -> Box<dyn Layer>;
117
118 fn as_any(&self) -> &dyn Any;
120
121 fn as_any_mut(&mut self) -> &mut dyn Any;
123
124 fn into_any(self: Box<Self>) -> Box<dyn Any>;
126}
127
128impl Clone for Box<dyn Layer> {
129 fn clone(&self) -> Self {
130 self.clone_layer()
131 }
132}
133
134#[derive(Debug, Clone, Copy)]
136pub struct LayerContext<'a> {
137 packet: &'a Packet,
138 index: usize,
139}
140
141impl<'a> LayerContext<'a> {
142 pub const fn new(packet: &'a Packet, index: usize) -> Self {
144 Self { packet, index }
145 }
146
147 pub const fn packet(self) -> &'a Packet {
149 self.packet
150 }
151
152 pub const fn index(self) -> usize {
154 self.index
155 }
156
157 pub fn previous(self) -> Option<&'a dyn Layer> {
159 self.index
160 .checked_sub(1)
161 .and_then(|index| self.packet.get(index))
162 }
163
164 pub fn next(self) -> Option<&'a dyn Layer> {
166 self.packet.get(self.index + 1)
167 }
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
172pub enum LinkType {
173 Raw,
175 Ethernet,
177 Ieee80211,
179 Radiotap,
181 BluetoothLeLl,
183 Ieee802154,
185 Ieee802154Tap,
187 LinuxCooked,
189 LinuxSll,
191 NullLoopback,
193}
194
195#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
197pub enum NetworkLayer {
198 Raw,
200 Ipv4,
202 Ipv6,
204}
205
206#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
208pub struct Raw {
209 bytes: Vec<u8>,
210}
211
212impl Raw {
213 pub const fn new() -> Self {
215 Self { bytes: Vec::new() }
216 }
217
218 pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
220 Self {
221 bytes: bytes.as_ref().to_vec(),
222 }
223 }
224
225 pub fn as_bytes(&self) -> &[u8] {
227 &self.bytes
228 }
229
230 pub fn as_bytes_mut(&mut self) -> &mut Vec<u8> {
232 &mut self.bytes
233 }
234
235 pub fn extend_from_slice(&mut self, bytes: &[u8]) -> &mut Self {
237 self.bytes.extend_from_slice(bytes);
238 self
239 }
240
241 pub fn into_bytes(self) -> Vec<u8> {
243 self.bytes
244 }
245
246 pub fn len(&self) -> usize {
248 self.bytes.len()
249 }
250
251 pub fn is_empty(&self) -> bool {
253 self.bytes.is_empty()
254 }
255
256 pub fn hexdump(&self) -> String {
258 hexdump(self.as_bytes())
259 }
260
261 pub fn raw_string_lossy(&self) -> String {
263 String::from_utf8_lossy(self.as_bytes()).into_owned()
264 }
265}
266
267impl Layer for Raw {
268 fn name(&self) -> &'static str {
269 "Raw"
270 }
271
272 fn summary(&self) -> String {
273 format!("Raw(len={})", self.bytes.len())
274 }
275
276 fn inspection_fields(&self) -> Vec<(&'static str, String)> {
277 vec![
278 ("len", self.bytes.len().to_string()),
279 ("bytes", hex_bytes(&self.bytes)),
280 ("text_lossy", quoted_lossy_text(self.as_bytes())),
281 ]
282 }
283
284 fn encoded_len(&self) -> usize {
285 self.bytes.len()
286 }
287
288 fn compile(&self, _ctx: &LayerContext<'_>, out: &mut Vec<u8>) -> Result<()> {
289 out.extend_from_slice(&self.bytes);
290 Ok(())
291 }
292
293 fn clone_layer(&self) -> Box<dyn Layer> {
294 Box::new(self.clone())
295 }
296
297 fn as_any(&self) -> &dyn Any {
298 self
299 }
300
301 fn as_any_mut(&mut self) -> &mut dyn Any {
302 self
303 }
304
305 fn into_any(self: Box<Self>) -> Box<dyn Any> {
306 self
307 }
308}
309
310impl From<Vec<u8>> for Raw {
311 fn from(bytes: Vec<u8>) -> Self {
312 Self { bytes }
313 }
314}
315
316impl From<&[u8]> for Raw {
317 fn from(bytes: &[u8]) -> Self {
318 Self::from_bytes(bytes)
319 }
320}
321
322impl<const N: usize> From<&[u8; N]> for Raw {
323 fn from(bytes: &[u8; N]) -> Self {
324 Self::from_bytes(bytes)
325 }
326}
327
328impl<const N: usize> From<[u8; N]> for Raw {
329 fn from(bytes: [u8; N]) -> Self {
330 Self::from_bytes(bytes)
331 }
332}
333
334impl From<&str> for Raw {
335 fn from(value: &str) -> Self {
336 Self::from_bytes(value.as_bytes())
337 }
338}
339
340impl From<String> for Raw {
341 fn from(value: String) -> Self {
342 Self::from_bytes(value.as_bytes())
343 }
344}
345
346#[derive(Debug, Clone)]
347enum PacketLayer {
348 Boxed(Box<dyn Layer>),
349 Raw(Raw),
350 Ethernet(Ethernet),
351 Vlan(Vlan),
352 Arp(Arp),
353 Ipv4(Ipv4),
354 Ipv6(Ipv6),
355 Tcp(Tcp),
356 Udp(Udp),
357 Icmpv4(Icmpv4),
358 Icmpv4QuotedIp(Icmpv4QuotedIp),
359 Icmpv6(Icmpv6),
360 Igmp(Igmp),
361 NeighborSolicitation(NeighborSolicitation),
362}
363
364impl PacketLayer {
365 fn as_layer(&self) -> &dyn Layer {
366 match self {
367 Self::Boxed(layer) => layer.as_ref(),
368 Self::Raw(layer) => layer,
369 Self::Ethernet(layer) => layer,
370 Self::Vlan(layer) => layer,
371 Self::Arp(layer) => layer,
372 Self::Ipv4(layer) => layer,
373 Self::Ipv6(layer) => layer,
374 Self::Tcp(layer) => layer,
375 Self::Udp(layer) => layer,
376 Self::Icmpv4(layer) => layer,
377 Self::Icmpv4QuotedIp(layer) => layer,
378 Self::Icmpv6(layer) => layer,
379 Self::Igmp(layer) => layer,
380 Self::NeighborSolicitation(layer) => layer,
381 }
382 }
383
384 fn as_layer_mut(&mut self) -> &mut dyn Layer {
385 match self {
386 Self::Boxed(layer) => layer.as_mut(),
387 Self::Raw(layer) => layer,
388 Self::Ethernet(layer) => layer,
389 Self::Vlan(layer) => layer,
390 Self::Arp(layer) => layer,
391 Self::Ipv4(layer) => layer,
392 Self::Ipv6(layer) => layer,
393 Self::Tcp(layer) => layer,
394 Self::Udp(layer) => layer,
395 Self::Icmpv4(layer) => layer,
396 Self::Icmpv4QuotedIp(layer) => layer,
397 Self::Icmpv6(layer) => layer,
398 Self::Igmp(layer) => layer,
399 Self::NeighborSolicitation(layer) => layer,
400 }
401 }
402
403 fn into_box(self) -> Box<dyn Layer> {
404 match self {
405 Self::Boxed(layer) => layer,
406 Self::Raw(layer) => Box::new(layer),
407 Self::Ethernet(layer) => Box::new(layer),
408 Self::Vlan(layer) => Box::new(layer),
409 Self::Arp(layer) => Box::new(layer),
410 Self::Ipv4(layer) => Box::new(layer),
411 Self::Ipv6(layer) => Box::new(layer),
412 Self::Tcp(layer) => Box::new(layer),
413 Self::Udp(layer) => Box::new(layer),
414 Self::Icmpv4(layer) => Box::new(layer),
415 Self::Icmpv4QuotedIp(layer) => Box::new(layer),
416 Self::Icmpv6(layer) => Box::new(layer),
417 Self::Igmp(layer) => Box::new(layer),
418 Self::NeighborSolicitation(layer) => Box::new(layer),
419 }
420 }
421
422 fn encoded_len_with_context(&self, ctx: &LayerContext<'_>) -> usize {
423 match self {
424 Self::Boxed(layer) => layer.encoded_len_with_context(ctx),
425 Self::Raw(layer) => layer.encoded_len_with_context(ctx),
426 Self::Ethernet(layer) => layer.encoded_len_with_context(ctx),
427 Self::Vlan(layer) => layer.encoded_len_with_context(ctx),
428 Self::Arp(layer) => layer.encoded_len_with_context(ctx),
429 Self::Ipv4(layer) => layer.encoded_len_with_context(ctx),
430 Self::Ipv6(layer) => layer.encoded_len_with_context(ctx),
431 Self::Tcp(layer) => layer.encoded_len_with_context(ctx),
432 Self::Udp(layer) => layer.encoded_len_with_context(ctx),
433 Self::Icmpv4(layer) => layer.encoded_len_with_context(ctx),
434 Self::Icmpv4QuotedIp(layer) => layer.encoded_len_with_context(ctx),
435 Self::Icmpv6(layer) => layer.encoded_len_with_context(ctx),
436 Self::Igmp(layer) => layer.encoded_len_with_context(ctx),
437 Self::NeighborSolicitation(layer) => layer.encoded_len_with_context(ctx),
438 }
439 }
440
441 fn compile(&self, ctx: &LayerContext<'_>, out: &mut Vec<u8>) -> Result<()> {
442 match self {
443 Self::Boxed(layer) => layer.compile(ctx, out),
444 Self::Raw(layer) => layer.compile(ctx, out),
445 Self::Ethernet(layer) => layer.compile(ctx, out),
446 Self::Vlan(layer) => layer.compile(ctx, out),
447 Self::Arp(layer) => layer.compile(ctx, out),
448 Self::Ipv4(layer) => layer.compile(ctx, out),
449 Self::Ipv6(layer) => layer.compile(ctx, out),
450 Self::Tcp(layer) => layer.compile(ctx, out),
451 Self::Udp(layer) => layer.compile(ctx, out),
452 Self::Icmpv4(layer) => layer.compile(ctx, out),
453 Self::Icmpv4QuotedIp(layer) => layer.compile(ctx, out),
454 Self::Icmpv6(layer) => layer.compile(ctx, out),
455 Self::Igmp(layer) => layer.compile(ctx, out),
456 Self::NeighborSolicitation(layer) => layer.compile(ctx, out),
457 }
458 }
459
460 fn consumes_following(&self) -> bool {
461 match self {
462 Self::Boxed(layer) => layer.consumes_following(),
463 Self::Raw(layer) => layer.consumes_following(),
464 Self::Ethernet(layer) => layer.consumes_following(),
465 Self::Vlan(layer) => layer.consumes_following(),
466 Self::Arp(layer) => layer.consumes_following(),
467 Self::Ipv4(layer) => layer.consumes_following(),
468 Self::Ipv6(layer) => layer.consumes_following(),
469 Self::Tcp(layer) => layer.consumes_following(),
470 Self::Udp(layer) => layer.consumes_following(),
471 Self::Icmpv4(layer) => layer.consumes_following(),
472 Self::Icmpv4QuotedIp(layer) => layer.consumes_following(),
473 Self::Icmpv6(layer) => layer.consumes_following(),
474 Self::Igmp(layer) => layer.consumes_following(),
475 Self::NeighborSolicitation(layer) => layer.consumes_following(),
476 }
477 }
478}
479
480#[derive(Debug, Clone, Default)]
482pub struct Packet {
483 layers: Vec<PacketLayer>,
484}
485
486impl Packet {
487 pub const fn new() -> Self {
489 Self { layers: Vec::new() }
490 }
491
492 pub(crate) fn with_capacity(capacity: usize) -> Self {
494 Self {
495 layers: Vec::with_capacity(capacity),
496 }
497 }
498
499 pub fn from_layer<L>(layer: L) -> Self
501 where
502 L: Layer,
503 {
504 Self::new().push(layer)
505 }
506
507 pub fn push<L>(mut self, layer: L) -> Self
509 where
510 L: Layer,
511 {
512 self.layers.push(PacketLayer::Boxed(Box::new(layer)));
513 self
514 }
515
516 pub fn push_box(mut self, layer: Box<dyn Layer>) -> Self {
518 self.layers.push(PacketLayer::Boxed(layer));
519 self
520 }
521
522 pub fn push_mut<L>(&mut self, layer: L) -> &mut Self
524 where
525 L: Layer,
526 {
527 self.layers.push(PacketLayer::Boxed(Box::new(layer)));
528 self
529 }
530
531 pub fn push_box_mut(&mut self, layer: Box<dyn Layer>) -> &mut Self {
533 self.layers.push(PacketLayer::Boxed(layer));
534 self
535 }
536
537 pub(crate) fn push_raw(mut self, layer: Raw) -> Self {
538 self.layers.push(PacketLayer::Raw(layer));
539 self
540 }
541
542 pub(crate) fn push_raw_mut(&mut self, layer: Raw) -> &mut Self {
543 self.layers.push(PacketLayer::Raw(layer));
544 self
545 }
546
547 pub(crate) fn push_ethernet(mut self, layer: Ethernet) -> Self {
548 self.layers.push(PacketLayer::Ethernet(layer));
549 self
550 }
551
552 pub(crate) fn push_ethernet_mut(&mut self, layer: Ethernet) -> &mut Self {
553 self.layers.push(PacketLayer::Ethernet(layer));
554 self
555 }
556
557 pub(crate) fn push_vlan(mut self, layer: Vlan) -> Self {
558 self.layers.push(PacketLayer::Vlan(layer));
559 self
560 }
561
562 pub(crate) fn push_arp_mut(&mut self, layer: Arp) -> &mut Self {
563 self.layers.push(PacketLayer::Arp(layer));
564 self
565 }
566
567 pub(crate) fn push_ipv4(mut self, layer: Ipv4) -> Self {
568 self.layers.push(PacketLayer::Ipv4(layer));
569 self
570 }
571
572 pub(crate) fn push_ipv4_mut(&mut self, layer: Ipv4) -> &mut Self {
573 self.layers.push(PacketLayer::Ipv4(layer));
574 self
575 }
576
577 pub(crate) fn push_ipv6(mut self, layer: Ipv6) -> Self {
578 self.layers.push(PacketLayer::Ipv6(layer));
579 self
580 }
581
582 pub(crate) fn push_tcp(mut self, layer: Tcp) -> Self {
583 self.layers.push(PacketLayer::Tcp(layer));
584 self
585 }
586
587 pub(crate) fn push_udp(mut self, layer: Udp) -> Self {
588 self.layers.push(PacketLayer::Udp(layer));
589 self
590 }
591
592 pub(crate) fn push_icmpv4_mut(&mut self, layer: Icmpv4) -> &mut Self {
593 self.layers.push(PacketLayer::Icmpv4(layer));
594 self
595 }
596
597 pub(crate) fn push_icmpv4_quoted_ip_mut(&mut self, layer: Icmpv4QuotedIp) -> &mut Self {
598 self.layers.push(PacketLayer::Icmpv4QuotedIp(layer));
599 self
600 }
601
602 pub(crate) fn push_icmpv6(mut self, layer: Icmpv6) -> Self {
603 self.layers.push(PacketLayer::Icmpv6(layer));
604 self
605 }
606
607 pub(crate) fn push_igmp(mut self, layer: Igmp) -> Self {
608 self.layers.push(PacketLayer::Igmp(layer));
609 self
610 }
611
612 pub(crate) fn push_neighbor_solicitation(mut self, layer: NeighborSolicitation) -> Self {
613 self.layers.push(PacketLayer::NeighborSolicitation(layer));
614 self
615 }
616
617 pub fn concat(mut self, other: impl IntoPacket) -> Self {
619 self.layers.extend(other.into_packet().layers);
620 self
621 }
622
623 pub fn extend(&mut self, other: impl IntoPacket) -> &mut Self {
625 self.layers.extend(other.into_packet().layers);
626 self
627 }
628
629 pub fn pop(&mut self) -> Option<Box<dyn Layer>> {
631 self.layers.pop().map(PacketLayer::into_box)
632 }
633
634 pub fn pop_typed<T>(&mut self) -> Option<T>
636 where
637 T: Layer,
638 {
639 let layer = self.pop()?;
640 if layer.as_any().is::<T>() {
641 let any = layer.into_any();
642 Some(*any.downcast::<T>().ok()?)
643 } else {
644 self.layers.push(PacketLayer::Boxed(layer));
645 None
646 }
647 }
648
649 pub fn len(&self) -> usize {
651 self.layers.len()
652 }
653
654 pub fn is_empty(&self) -> bool {
656 self.layers.is_empty()
657 }
658
659 pub fn encoded_len(&self) -> usize {
661 let mut total = 0;
662 for (index, layer) in self.layers.iter().enumerate() {
663 let ctx = LayerContext::new(self, index);
664 total += layer.encoded_len_with_context(&ctx);
665 if layer.consumes_following() {
668 break;
669 }
670 }
671 total
672 }
673
674 pub fn get(&self, index: usize) -> Option<&dyn Layer> {
676 self.layers.get(index).map(PacketLayer::as_layer)
677 }
678
679 pub fn get_mut(&mut self, index: usize) -> Option<&mut dyn Layer> {
681 self.layers.get_mut(index).map(PacketLayer::as_layer_mut)
682 }
683
684 pub(crate) fn single_raw_layer_after(&self, index: usize) -> Option<&Raw> {
685 let next = index.checked_add(1)?;
686 if self.layers.len() != next.checked_add(1)? {
687 return None;
688 }
689 match self.layers.get(next)? {
690 PacketLayer::Raw(raw) => Some(raw),
691 PacketLayer::Boxed(layer) => layer.as_any().downcast_ref::<Raw>(),
692 _ => None,
693 }
694 }
695
696 pub fn layer<T>(&self) -> Option<&T>
698 where
699 T: Layer,
700 {
701 self.layers
702 .iter()
703 .find_map(|layer| layer.as_layer().as_any().downcast_ref::<T>())
704 }
705
706 pub fn layer_mut<T>(&mut self) -> Option<&mut T>
708 where
709 T: Layer,
710 {
711 self.layers
712 .iter_mut()
713 .find_map(|layer| layer.as_layer_mut().as_any_mut().downcast_mut::<T>())
714 }
715
716 pub fn layers<T>(&self) -> impl Iterator<Item = &T>
718 where
719 T: Layer,
720 {
721 self.layers
722 .iter()
723 .filter_map(|layer| layer.as_layer().as_any().downcast_ref::<T>())
724 }
725
726 pub fn layers_mut<T>(&mut self) -> impl Iterator<Item = &mut T>
728 where
729 T: Layer,
730 {
731 self.layers
732 .iter_mut()
733 .filter_map(|layer| layer.as_layer_mut().as_any_mut().downcast_mut::<T>())
734 }
735
736 pub fn iter(&self) -> impl Iterator<Item = &dyn Layer> {
738 self.layers.iter().map(PacketLayer::as_layer)
739 }
740
741 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut dyn Layer> {
743 self.layers.iter_mut().map(PacketLayer::as_layer_mut)
744 }
745
746 pub fn compile(&self) -> Result<CompiledPacket> {
748 let mut bytes = Vec::with_capacity(self.encoded_len());
749 self.compile_into(&mut bytes)?;
750 Ok(CompiledPacket::new(bytes))
751 }
752
753 pub fn compile_into(&self, out: &mut Vec<u8>) -> Result<()> {
755 for (index, layer) in self.layers.iter().enumerate() {
756 let ctx = LayerContext::new(self, index);
757 layer.compile(&ctx, out)?;
758 if layer.consumes_following() {
762 break;
763 }
764 }
765 Ok(())
766 }
767
768 pub(crate) fn compile_layers_after_into(&self, index: usize, out: &mut Vec<u8>) -> Result<()> {
769 for (layer_index, layer) in self.layers.iter().enumerate().skip(index + 1) {
770 let ctx = LayerContext::new(self, layer_index);
771 layer.compile(&ctx, out)?;
772 if layer.consumes_following() {
773 break;
774 }
775 }
776 Ok(())
777 }
778
779 pub(crate) fn compile_all_layers_after_into(
780 &self,
781 index: usize,
782 out: &mut Vec<u8>,
783 ) -> Result<()> {
784 for (layer_index, layer) in self.layers.iter().enumerate().skip(index + 1) {
785 let ctx = LayerContext::new(self, layer_index);
786 layer.compile(&ctx, out)?;
787 }
788 Ok(())
789 }
790
791 pub(crate) fn encoded_len_after(&self, index: usize) -> usize {
792 let mut total = 0;
793 for (layer_index, layer) in self.layers.iter().enumerate().skip(index + 1) {
794 let ctx = LayerContext::new(self, layer_index);
795 total += layer.encoded_len_with_context(&ctx);
796 if layer.consumes_following() {
797 break;
798 }
799 }
800 total
801 }
802
803 pub fn decode_raw(bytes: impl AsRef<[u8]>) -> Result<Self> {
805 Ok(Self::new().push(Raw::from_bytes(bytes)))
806 }
807
808 pub fn decode_from_link(link_type: LinkType, bytes: impl AsRef<[u8]>) -> Result<Self> {
810 ProtocolRegistry::builtin().decode_from_link(link_type, bytes)
811 }
812
813 pub fn decode_from_link_with_registry(
815 registry: &ProtocolRegistry,
816 link_type: LinkType,
817 bytes: impl AsRef<[u8]>,
818 ) -> Result<Self> {
819 registry.decode_from_link(link_type, bytes)
820 }
821
822 pub fn decode_from_l3(network_layer: NetworkLayer, bytes: impl AsRef<[u8]>) -> Result<Self> {
824 ProtocolRegistry::builtin().decode_from_l3(network_layer, bytes)
825 }
826
827 pub fn decode_from_l3_with_registry(
829 registry: &ProtocolRegistry,
830 network_layer: NetworkLayer,
831 bytes: impl AsRef<[u8]>,
832 ) -> Result<Self> {
833 registry.decode_from_l3(network_layer, bytes)
834 }
835
836 pub fn summary(&self) -> String {
838 if self.layers.is_empty() {
839 "Packet(empty)".to_string()
840 } else {
841 self.layers
842 .iter()
843 .map(|layer| layer.as_layer().summary())
844 .collect::<Vec<_>>()
845 .join(" / ")
846 }
847 }
848
849 pub fn show(&self) -> String {
851 if self.layers.is_empty() {
852 return "Packet(empty)".to_string();
853 }
854
855 let mut output = format!(
856 "Packet(len={}, layers={})",
857 self.encoded_len(),
858 self.layers.len()
859 );
860 for (index, layer) in self.layers.iter().enumerate() {
861 let layer = layer.as_layer();
862 output.push_str(&format!("\n [{index}] {}", layer.name()));
863 for (name, value) in layer.inspection_fields() {
864 output.push_str(&format!("\n {name}: {value}"));
865 }
866 }
867 output
868 }
869
870 pub fn hexdump(&self) -> Result<String> {
872 Ok(hexdump(self.compile()?.as_bytes()))
873 }
874
875 pub fn raw_string_lossy(&self) -> Result<String> {
877 Ok(String::from_utf8_lossy(self.compile()?.as_bytes()).into_owned())
878 }
879}
880
881pub trait IntoPacket {
883 fn into_packet(self) -> Packet;
885}
886
887impl IntoPacket for Packet {
888 fn into_packet(self) -> Packet {
889 self
890 }
891}
892
893impl<T> IntoPacket for T
894where
895 T: Layer,
896{
897 fn into_packet(self) -> Packet {
898 Packet::from_layer(self)
899 }
900}
901
902impl IntoPacket for Box<dyn Layer> {
903 fn into_packet(self) -> Packet {
904 Packet::new().push_box(self)
905 }
906}
907
908impl<R> Div<R> for Packet
909where
910 R: IntoPacket,
911{
912 type Output = Packet;
913
914 fn div(self, rhs: R) -> Self::Output {
915 self.concat(rhs)
916 }
917}
918
919impl<R> Div<R> for Raw
920where
921 R: IntoPacket,
922{
923 type Output = Packet;
924
925 fn div(self, rhs: R) -> Self::Output {
926 Packet::from_layer(self).concat(rhs)
927 }
928}
929
930#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
932pub struct CompiledPacket {
933 bytes: Vec<u8>,
934}
935
936impl CompiledPacket {
937 pub fn new(bytes: Vec<u8>) -> Self {
939 Self { bytes }
940 }
941
942 pub fn as_bytes(&self) -> &[u8] {
944 &self.bytes
945 }
946
947 pub fn into_bytes(self) -> Vec<u8> {
949 self.bytes
950 }
951
952 pub fn len(&self) -> usize {
954 self.bytes.len()
955 }
956
957 pub fn is_empty(&self) -> bool {
959 self.bytes.is_empty()
960 }
961
962 pub fn hexdump(&self) -> String {
964 hexdump(self.as_bytes())
965 }
966
967 pub fn raw_string_lossy(&self) -> String {
969 String::from_utf8_lossy(self.as_bytes()).into_owned()
970 }
971}
972
973impl AsRef<[u8]> for CompiledPacket {
974 fn as_ref(&self) -> &[u8] {
975 self.as_bytes()
976 }
977}
978
979impl core::ops::Deref for CompiledPacket {
980 type Target = [u8];
981
982 fn deref(&self) -> &Self::Target {
983 self.as_bytes()
984 }
985}
986
987impl From<CompiledPacket> for Vec<u8> {
988 fn from(packet: CompiledPacket) -> Self {
989 packet.into_bytes()
990 }
991}
992
993pub fn hexdump(bytes: &[u8]) -> String {
995 let mut output = String::new();
996
997 for (offset, chunk) in bytes.chunks(16).enumerate() {
998 if offset > 0 {
999 output.push('\n');
1000 }
1001
1002 output.push_str(&format!("{:04x}: ", offset * 16));
1003 for (index, byte) in chunk.iter().enumerate() {
1004 if index > 0 {
1005 output.push(' ');
1006 }
1007 output.push_str(&format!("{byte:02x}"));
1008 }
1009 }
1010
1011 output
1012}
1013
1014fn hex_bytes(bytes: &[u8]) -> String {
1015 let mut output = String::new();
1016
1017 for (index, byte) in bytes.iter().enumerate() {
1018 if index > 0 {
1019 output.push(' ');
1020 }
1021 output.push_str(&format!("{byte:02x}"));
1022 }
1023
1024 output
1025}
1026
1027fn quoted_lossy_text(bytes: &[u8]) -> String {
1028 let text = String::from_utf8_lossy(bytes);
1029 let mut output = String::from("\"");
1030
1031 for ch in text.chars() {
1032 match ch {
1033 '\0' => output.push_str("\\0"),
1034 '\n' => output.push_str("\\n"),
1035 '\r' => output.push_str("\\r"),
1036 '\t' => output.push_str("\\t"),
1037 '"' => output.push_str("\\\""),
1038 '\\' => output.push_str("\\\\"),
1039 ch if ch.is_control() => output.extend(ch.escape_default()),
1040 ch if ch.is_ascii() => output.push(ch),
1041 ch => output.extend(ch.escape_default()),
1042 }
1043 }
1044
1045 output.push('"');
1046 output
1047}
1048
1049#[cfg(test)]
1050mod raw_layer {
1051 use super::{Layer, Packet, Raw};
1052
1053 #[test]
1054 fn raw_layer_preserves_bytes() {
1055 let raw = Raw::from_bytes(b"hello");
1056
1057 assert_eq!(raw.name(), "Raw");
1058 assert_eq!(raw.len(), 5);
1059 assert_eq!(raw.as_bytes(), b"hello");
1060 assert_eq!(raw.clone().into_bytes(), b"hello".to_vec());
1061 assert_eq!(raw.summary(), "Raw(len=5)");
1062 }
1063
1064 #[test]
1065 fn raw_layer_compiles_to_its_payload() {
1066 let packet = Packet::new().push(Raw::from("hello"));
1067
1068 assert_eq!(packet.compile().unwrap().as_bytes(), b"hello");
1069 assert_eq!(packet.raw_string_lossy().unwrap(), "hello");
1070 }
1071
1072 #[test]
1073 fn raw_decode_preserves_unknown_bytes() {
1074 let decoded = Packet::decode_raw([0xde, 0xad, 0xbe, 0xef]).unwrap();
1075 let raw = decoded.layer::<Raw>().unwrap();
1076
1077 assert_eq!(decoded.len(), 1);
1078 assert_eq!(raw.as_bytes(), [0xde, 0xad, 0xbe, 0xef]);
1079 }
1080}
1081
1082#[cfg(test)]
1083mod igmp_packet_storage {
1084 use super::{Packet, Raw};
1085 use crate::protocols::igmp::{append_igmp_packet, Igmp};
1086 use core::net::Ipv4Addr;
1087
1088 #[test]
1089 fn helper_storage_clones_downcasts_inspects_encodes_and_pops_igmp() {
1090 let group = Ipv4Addr::new(224, 0, 0, 251);
1091 let mut packet = Packet::new().push_igmp(
1092 Igmp::v2_membership_report(group)
1093 .with_code(0x05)
1094 .checksum(0x1234),
1095 );
1096
1097 let igmp = packet.layer::<Igmp>().expect("typed IGMP layer");
1098 assert_eq!(igmp.group_address_value(), group);
1099 assert_eq!(igmp.code_value(), 0x05);
1100 assert_eq!(packet.get(0).expect("first layer").name(), "Igmp");
1101 assert_eq!(
1102 packet.summary(),
1103 "Igmp(version=IGMPv2, type=0x16 (IGMPv2 Membership Report), code=0x05 (No registered code), group=224.0.0.251 (multicast), checksum=0x1234, checksum_status=not_checked)"
1104 );
1105
1106 let show = packet.show();
1107 assert!(show.contains("Packet(len=8, layers=1)"), "{show}");
1108 assert!(show.contains("[0] Igmp"), "{show}");
1109 assert!(
1110 show.contains("type: 0x16 (IGMPv2 Membership Report)"),
1111 "{show}"
1112 );
1113 assert!(show.contains("checksum: 0x1234"), "{show}");
1114
1115 let cloned = packet.clone();
1116 assert_eq!(
1117 cloned
1118 .layer::<Igmp>()
1119 .expect("cloned typed IGMP layer")
1120 .checksum_value(),
1121 Some(0x1234)
1122 );
1123 assert_eq!(
1124 packet.compile().expect("compile stored IGMP").as_bytes(),
1125 &[0x16, 0x05, 0x12, 0x34, 224, 0, 0, 251]
1126 );
1127
1128 let popped = packet.pop_typed::<Igmp>().expect("pop typed IGMP");
1129 assert_eq!(popped.group_address_value(), group);
1130 assert!(packet.is_empty());
1131 }
1132
1133 #[test]
1134 fn decoded_igmp_uses_typed_storage_and_preserves_raw_tail() {
1135 let bytes = [0x16, 0x00, 0xab, 0xcd, 224, 0, 0, 251, 0xde, 0xad];
1136
1137 let decoded =
1138 append_igmp_packet(Packet::new(), &bytes).expect("append decoded IGMP packet");
1139 let igmp = decoded.layer::<Igmp>().expect("typed decoded IGMP");
1140 let raw = decoded.layer::<Raw>().expect("preserved raw IGMP tail");
1141
1142 assert_eq!(decoded.len(), 2);
1143 assert_eq!(decoded.get(0).expect("first layer").name(), "Igmp");
1144 assert_eq!(igmp.igmp_type_value(), 0x16);
1145 assert_eq!(igmp.checksum_value(), Some(0xabcd));
1146 assert_eq!(igmp.group_address_value(), Ipv4Addr::new(224, 0, 0, 251));
1147 assert_eq!(raw.as_bytes(), &[0xde, 0xad]);
1148 assert_eq!(
1149 decoded
1150 .compile()
1151 .expect("roundtrip decoded IGMP")
1152 .as_bytes(),
1153 &bytes
1154 );
1155 }
1156}
1157
1158#[cfg(test)]
1159mod packet_stack {
1160 use super::{hexdump, Layer, LinkType, NetworkLayer, Packet, Raw};
1161
1162 #[test]
1163 fn builder_push_preserves_layer_order() {
1164 let packet = Packet::new()
1165 .push(Raw::from("first"))
1166 .push(Raw::from("second"));
1167
1168 let layers: Vec<_> = packet.layers::<Raw>().map(Raw::as_bytes).collect();
1169
1170 assert_eq!(packet.len(), 2);
1171 assert_eq!(layers, vec![b"first".as_slice(), b"second".as_slice()]);
1172 assert_eq!(packet.summary(), "Raw(len=5) / Raw(len=6)");
1173 }
1174
1175 #[test]
1176 fn slash_composition_builds_packets() {
1177 let packet = Raw::from("a") / Raw::from("b") / Packet::new().push(Raw::from("c"));
1178
1179 assert_eq!(packet.len(), 3);
1180 assert_eq!(packet.compile().unwrap().as_bytes(), b"abc");
1181 }
1182
1183 #[test]
1184 fn concat_and_pop_keep_stack_predictable() {
1185 let mut packet = Packet::new()
1186 .push(Raw::from("a"))
1187 .concat(Packet::new().push(Raw::from("b")));
1188
1189 assert_eq!(packet.compile().unwrap().as_bytes(), b"ab");
1190
1191 let popped = packet.pop_typed::<Raw>().unwrap();
1192
1193 assert_eq!(popped.as_bytes(), b"b");
1194 assert_eq!(packet.compile().unwrap().as_bytes(), b"a");
1195 }
1196
1197 #[test]
1198 fn typed_access_supports_mutation_and_ordered_iteration() {
1199 let mut packet = Packet::new().push(Raw::from("one")).push(Raw::from("two"));
1200
1201 packet.layer_mut::<Raw>().unwrap().extend_from_slice(b"!");
1202
1203 let names: Vec<_> = packet.iter().map(Layer::name).collect();
1204 let bytes: Vec<_> = packet.layers::<Raw>().map(Raw::as_bytes).collect();
1205
1206 assert_eq!(names, vec!["Raw", "Raw"]);
1207 assert_eq!(bytes, vec![b"one!".as_slice(), b"two".as_slice()]);
1208 }
1209
1210 #[test]
1211 fn raw_decode_entrypoints_are_lossless_raw_packets() {
1212 let link = Packet::decode_from_link(LinkType::Raw, b"frame").unwrap();
1213 let l3 = Packet::decode_from_l3(NetworkLayer::Raw, b"packet").unwrap();
1214
1215 assert_eq!(link.compile().unwrap().as_bytes(), b"frame");
1216 assert_eq!(l3.compile().unwrap().as_bytes(), b"packet");
1217 }
1218
1219 #[test]
1220 fn inspection_helpers_are_stable() {
1221 let packet = Packet::new().push(Raw::from([0x41, 0x42, 0x43].as_slice()));
1222
1223 assert_eq!(
1224 packet.show(),
1225 "Packet(len=3, layers=1)\n [0] Raw\n len: 3\n bytes: 41 42 43\n text_lossy: \"ABC\""
1226 );
1227 assert_eq!(packet.hexdump().unwrap(), "0000: 41 42 43");
1228 assert_eq!(hexdump(&[]), "");
1229 }
1230}
1231
1232#[cfg(test)]
1233mod formatting {
1234 use super::{hexdump, Layer, Packet, Raw};
1235
1236 const RAW_ONLY_SUMMARY: &str = fixture_str!("summaries/raw-hello-agents.summary.txt");
1237
1238 fn raw_only_packet() -> Packet {
1239 Packet::new().push(Raw::from("Hello, agents!"))
1240 }
1241
1242 fn raw_only_snapshot() -> String {
1243 let packet = raw_only_packet();
1244
1245 format!(
1246 "summary:\n{}\n\nshow:\n{}\n\nhexdump:\n{}\n\nraw_string_lossy_debug:\n{:?}\n",
1247 packet.summary(),
1248 packet.show(),
1249 packet.hexdump().unwrap(),
1250 packet.raw_string_lossy().unwrap()
1251 )
1252 }
1253
1254 #[test]
1255 fn formatting_raw_only_packet_matches_summary_fixture() {
1256 assert_eq!(raw_only_snapshot(), RAW_ONLY_SUMMARY);
1257 }
1258
1259 #[test]
1260 fn formatting_empty_packet_is_stable() {
1261 let packet = Packet::new();
1262
1263 assert_eq!(packet.summary(), "Packet(empty)");
1264 assert_eq!(packet.show(), "Packet(empty)");
1265 assert_eq!(packet.hexdump().unwrap(), "");
1266 assert_eq!(packet.raw_string_lossy().unwrap(), "");
1267 }
1268
1269 #[test]
1270 fn formatting_raw_layer_helpers_are_stable() {
1271 let raw = Raw::from([0x48, 0x69, 0xff, 0x00].as_slice());
1272
1273 assert_eq!(raw.summary(), "Raw(len=4)");
1274 assert_eq!(raw.hexdump(), "0000: 48 69 ff 00");
1275 assert_eq!(raw.raw_string_lossy(), "Hi\u{fffd}\0");
1276 assert_eq!(
1277 raw.inspection_fields(),
1278 vec![
1279 ("len", "4".to_string()),
1280 ("bytes", "48 69 ff 00".to_string()),
1281 ("text_lossy", "\"Hi\\u{fffd}\\0\"".to_string()),
1282 ]
1283 );
1284 }
1285
1286 #[test]
1287 fn formatting_hexdump_chunks_sixteen_bytes_per_line() {
1288 let bytes: Vec<u8> = (0x00..=0x11).collect();
1289
1290 assert_eq!(
1291 hexdump(&bytes),
1292 "0000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n0010: 10 11"
1293 );
1294 }
1295}