Skip to main content

stackforge_core/layer/
mod.rs

1//! Layer definitions and enum dispatch for protocol handling.
2//!
3//! This module implements the "Lazy Zero-Copy View" architecture where layers
4//! are represented as lightweight views into a raw packet buffer.
5
6pub mod arp;
7pub mod bindings;
8pub mod dns;
9pub mod dot11;
10pub mod dot15d4;
11pub mod ethernet;
12pub mod field;
13pub mod field_ext;
14pub mod generic;
15pub mod http;
16pub mod http2;
17pub mod icmp;
18pub mod icmpv6;
19pub mod ipv4;
20pub mod ipv6;
21pub mod l2tp;
22pub mod neighbor;
23pub mod quic;
24pub mod raw;
25pub mod ssh;
26pub mod stack;
27pub mod tcp;
28pub mod tls;
29pub mod udp;
30
31use std::ops::Range;
32
33// Re-export layer types
34pub use arp::{ArpBuilder, ArpLayer};
35pub use bindings::{LAYER_BINDINGS, LayerBinding};
36pub use ethernet::{Dot3Builder, Dot3Layer, EthernetBuilder, EthernetLayer};
37pub use field::{BytesField, Field, FieldDesc, FieldError, FieldType, FieldValue, MacAddress};
38pub use http::{HTTP_FIELD_NAMES, HttpLayer, HttpRequestBuilder, HttpResponseBuilder};
39pub use http2::{HTTP2_FIELD_NAMES, Http2Builder, Http2FrameBuilder, Http2Layer};
40pub use icmp::{ICMP_MIN_HEADER_LEN, IcmpBuilder, IcmpLayer, icmp_checksum, verify_icmp_checksum};
41pub use icmpv6::{
42    ICMPV6_MIN_HEADER_LEN, Icmpv6Builder, Icmpv6Layer, icmpv6_checksum, verify_icmpv6_checksum,
43};
44pub use ipv4::{Ipv4Builder, Ipv4Flags, Ipv4Layer, Ipv4Options, Ipv4Route};
45pub use ipv6::{IPV6_HEADER_LEN, Ipv6Builder, Ipv6Layer};
46pub use l2tp::{L2TP_FIELD_NAMES, L2TP_MIN_HEADER_LEN, L2TP_PORT, L2tpBuilder, L2tpLayer};
47pub use neighbor::{NeighborCache, NeighborResolver};
48pub use raw::{RAW_FIELDS, RawBuilder, RawLayer};
49pub use ssh::{SSH_BINARY_HEADER_LEN, SSH_PORT, SshBuilder, SshLayer};
50pub use stack::{IntoLayerStackEntry, LayerStack, LayerStackEntry};
51pub use tcp::{
52    TCP_FIELDS, TCP_MAX_HEADER_LEN, TCP_MIN_HEADER_LEN, TCP_SERVICES, TcpAoValue, TcpBuilder,
53    TcpFlags, TcpLayer, TcpOption, TcpOptionKind, TcpOptions, TcpOptionsBuilder, TcpSackBlock,
54    TcpTimestamp, service_name, service_port, tcp_checksum, tcp_checksum_ipv4, verify_tcp_checksum,
55};
56pub use tls::{
57    TLS_FIELDS, TLS_PORT, TLS_RECORD_HEADER_LEN, TlsAlertBuilder, TlsCcsBuilder, TlsContentType,
58    TlsLayer, TlsRecordBuilder, TlsVersion,
59};
60pub use udp::{
61    UDP_HEADER_LEN, UdpBuilder, UdpLayer, udp_checksum_ipv4, udp_checksum_ipv6,
62    verify_udp_checksum_ipv4, verify_udp_checksum_ipv6,
63};
64
65/// Identifies the type of network protocol layer.
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
67#[repr(u8)]
68pub enum LayerKind {
69    Ethernet = 0,
70    Dot3 = 1,
71    Arp = 2,
72    Ipv4 = 3,
73    Ipv6 = 4,
74    Icmp = 5,
75    Icmpv6 = 6,
76    Tcp = 7,
77    Udp = 8,
78    Dns = 9,
79    Dot1Q = 10,
80    Dot1AD = 11,
81    Dot1AH = 12,
82    LLC = 13,
83    SNAP = 14,
84    Ssh = 15,
85    Tls = 16,
86    Dot15d4 = 17,
87    Dot15d4Fcs = 18,
88    Dot11 = 19,
89    Http = 20,
90    Quic = 21,
91    Generic = 22,
92    Http2 = 23,
93    L2tp = 24,
94    Raw = 255,
95}
96
97impl LayerKind {
98    #[inline]
99    pub const fn name(&self) -> &'static str {
100        match self {
101            Self::Ethernet => "Ethernet",
102            Self::Dot3 => "802.3",
103            Self::Arp => "ARP",
104            Self::Ipv4 => "IPv4",
105            Self::Ipv6 => "IPv6",
106            Self::Icmp => "ICMP",
107            Self::Icmpv6 => "ICMPv6",
108            Self::Tcp => "TCP",
109            Self::Udp => "UDP",
110            Self::Dns => "DNS",
111            Self::Dot1Q => "802.1Q",
112            Self::Dot1AD => "802.1AD",
113            Self::Dot1AH => "802.1AH",
114            Self::LLC => "LLC",
115            Self::SNAP => "SNAP",
116            Self::Ssh => "SSH",
117            Self::Tls => "TLS",
118            Self::Dot15d4 => "802.15.4",
119            Self::Dot15d4Fcs => "802.15.4 FCS",
120            Self::Dot11 => "802.11",
121            Self::Http => "HTTP",
122            Self::Quic => "QUIC",
123            Self::Generic => "Generic",
124            Self::Http2 => "HTTP/2",
125            Self::L2tp => "L2TP",
126            Self::Raw => "Raw",
127        }
128    }
129
130    #[inline]
131    pub const fn min_header_size(&self) -> usize {
132        match self {
133            Self::Ethernet | Self::Dot3 => ethernet::ETHERNET_HEADER_LEN,
134            Self::Arp => arp::ARP_HEADER_LEN,
135            Self::Ipv4 => ipv4::IPV4_MIN_HEADER_LEN,
136            Self::Ipv6 => 40,
137            Self::Icmp | Self::Icmpv6 => 8,
138            Self::Tcp => tcp::TCP_MIN_HEADER_LEN,
139            Self::Udp => 8,
140            Self::Dns => 12,
141            Self::Dot1Q => 4,
142            Self::Dot1AD => 4,
143            Self::Dot1AH => 6,
144            Self::LLC => 3,
145            Self::SNAP => 5,
146            Self::Ssh => ssh::SSH_BINARY_HEADER_LEN,
147            Self::Tls => tls::TLS_RECORD_HEADER_LEN,
148            Self::Dot15d4 => 3,    // minimum: 2 bytes FCF + 1 byte seqnum
149            Self::Dot15d4Fcs => 5, // minimum: 2 bytes FCF + 1 byte seqnum + 2 bytes FCS
150            Self::Dot11 => dot11::DOT11_MIN_HEADER_LEN,
151            Self::Http => 14, // minimum: "GET / HTTP/1.1\r\n\r\n" is ~18 bytes, but use 14 as min
152            Self::Quic => quic::QUIC_MIN_HEADER_LEN,
153            Self::Generic => 0,
154            Self::Http2 => 9, // 9-byte frame header
155            Self::L2tp => l2tp::L2TP_MIN_HEADER_LEN,
156            Self::Raw => 0,
157        }
158    }
159
160    /// Check if this is a link layer protocol
161    #[inline]
162    pub const fn is_link_layer(&self) -> bool {
163        matches!(
164            self,
165            Self::Ethernet | Self::Dot3 | Self::Dot1Q | Self::Dot1AD | Self::Dot1AH
166        )
167    }
168
169    /// Check if this is a network layer protocol
170    #[inline]
171    pub const fn is_network_layer(&self) -> bool {
172        matches!(self, Self::Ipv4 | Self::Ipv6 | Self::Arp)
173    }
174
175    /// Check if this is a transport layer protocol
176    #[inline]
177    pub const fn is_transport_layer(&self) -> bool {
178        matches!(self, Self::Tcp | Self::Udp | Self::Icmp | Self::Icmpv6)
179    }
180}
181
182impl std::fmt::Display for LayerKind {
183    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184        write!(f, "{}", self.name())
185    }
186}
187
188/// Index information for a layer within a packet buffer.
189#[derive(Debug, Clone, Copy, PartialEq, Eq)]
190pub struct LayerIndex {
191    pub kind: LayerKind,
192    pub start: usize,
193    pub end: usize,
194}
195
196impl LayerIndex {
197    #[inline]
198    pub const fn new(kind: LayerKind, start: usize, end: usize) -> Self {
199        Self { kind, start, end }
200    }
201
202    #[inline]
203    pub const fn range(&self) -> Range<usize> {
204        self.start..self.end
205    }
206
207    #[inline]
208    pub const fn len(&self) -> usize {
209        self.end - self.start
210    }
211
212    #[inline]
213    pub const fn is_empty(&self) -> bool {
214        self.start == self.end
215    }
216
217    /// Get the bytes for this layer from a buffer
218    #[inline]
219    pub fn slice<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
220        &buf[self.start..self.end.min(buf.len())]
221    }
222
223    /// Get mutable bytes for this layer from a buffer
224    #[inline]
225    pub fn slice_mut<'a>(&self, buf: &'a mut [u8]) -> &'a mut [u8] {
226        let end = self.end.min(buf.len());
227        &mut buf[self.start..end]
228    }
229
230    /// Get payload bytes (everything after this layer)
231    #[inline]
232    pub fn payload<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
233        &buf[self.end.min(buf.len())..]
234    }
235}
236
237/// Trait for types that can act as a network protocol layer.
238///
239/// This trait defines the core interface for all protocol layers,
240/// including methods for packet matching (hashret/answers) and
241/// padding extraction
242pub trait Layer {
243    /// Get the kind of this layer
244    fn kind(&self) -> LayerKind;
245
246    /// Get a human-readable summary of this layer
247    fn summary(&self, data: &[u8]) -> String;
248
249    /// Get the header length for this layer
250    fn header_len(&self, data: &[u8]) -> usize;
251
252    /// Compute a hash for packet matching.
253    fn hashret(&self, _data: &[u8]) -> Vec<u8> {
254        vec![]
255    }
256
257    /// Check if this packet answers another packet.
258    fn answers(&self, _data: &[u8], _other: &Self, _other_data: &[u8]) -> bool {
259        false
260    }
261
262    /// Extract padding from the packet.
263    fn extract_padding<'a>(&self, data: &'a [u8]) -> (&'a [u8], &'a [u8]) {
264        let header_len = self.header_len(data);
265        (&data[header_len..], &[])
266    }
267
268    /// Get the list of field names for this layer
269    fn field_names(&self) -> &'static [&'static str] {
270        &[]
271    }
272}
273
274/// Enum dispatch for protocol layers.
275#[derive(Debug, Clone)]
276pub enum LayerEnum {
277    Ethernet(EthernetLayer),
278    Dot3(Dot3Layer),
279    Arp(ArpLayer),
280    Ipv4(Ipv4Layer),
281    Ipv6(Ipv6Layer),
282    Icmp(IcmpLayer),
283    Icmpv6(Icmpv6Layer),
284    Tcp(TcpLayer),
285    Udp(UdpLayer),
286    Dns(DnsLayer),
287    Ssh(SshLayer),
288    Tls(TlsLayer),
289    Dot15d4(dot15d4::Dot15d4Layer),
290    Dot15d4Fcs(dot15d4::Dot15d4FcsLayer),
291    Dot11(dot11::Dot11Layer),
292    Http(http::HttpLayer),
293    Http2(http2::Http2Layer),
294    Quic(quic::QuicLayer),
295    L2tp(l2tp::L2tpLayer),
296    Raw(RawLayer),
297}
298
299impl LayerEnum {
300    #[inline]
301    pub fn kind(&self) -> LayerKind {
302        match self {
303            Self::Ethernet(_) => LayerKind::Ethernet,
304            Self::Dot3(_) => LayerKind::Dot3,
305            Self::Arp(_) => LayerKind::Arp,
306            Self::Ipv4(_) => LayerKind::Ipv4,
307            Self::Ipv6(_) => LayerKind::Ipv6,
308            Self::Icmp(_) => LayerKind::Icmp,
309            Self::Icmpv6(_) => LayerKind::Icmpv6,
310            Self::Tcp(_) => LayerKind::Tcp,
311            Self::Udp(_) => LayerKind::Udp,
312            Self::Dns(_) => LayerKind::Dns,
313            Self::Ssh(_) => LayerKind::Ssh,
314            Self::Tls(_) => LayerKind::Tls,
315            Self::Dot15d4(_) => LayerKind::Dot15d4,
316            Self::Dot15d4Fcs(_) => LayerKind::Dot15d4Fcs,
317            Self::Dot11(_) => LayerKind::Dot11,
318            Self::Http(_) => LayerKind::Http,
319            Self::Http2(_) => LayerKind::Http2,
320            Self::Quic(_) => LayerKind::Quic,
321            Self::L2tp(_) => LayerKind::L2tp,
322            Self::Raw(_) => LayerKind::Raw,
323        }
324    }
325
326    #[inline]
327    pub fn index(&self) -> &LayerIndex {
328        match self {
329            Self::Ethernet(l) => &l.index,
330            Self::Dot3(l) => &l.index,
331            Self::Arp(l) => &l.index,
332            Self::Ipv4(l) => &l.index,
333            Self::Ipv6(l) => &l.index,
334            Self::Icmp(l) => &l.index,
335            Self::Icmpv6(l) => &l.index,
336            Self::Tcp(l) => &l.index,
337            Self::Udp(l) => &l.index,
338            Self::Dns(l) => &l.index,
339            Self::Ssh(l) => &l.index,
340            Self::Tls(l) => &l.index,
341            Self::Dot15d4(l) => &l.index,
342            Self::Dot15d4Fcs(l) => &l.index,
343            Self::Dot11(l) => &l.index,
344            Self::Http(l) => &l.index,
345            Self::Http2(l) => &l.index,
346            Self::Quic(l) => &l.index,
347            Self::L2tp(l) => &l.index,
348            Self::Raw(l) => &l.index,
349        }
350    }
351
352    pub fn summary(&self, buf: &[u8]) -> String {
353        match self {
354            Self::Ethernet(l) => l.summary(buf),
355            Self::Dot3(l) => l.summary(buf),
356            Self::Arp(l) => l.summary(buf),
357            Self::Ipv4(l) => l.summary(buf),
358            Self::Ipv6(l) => l.summary(buf),
359            Self::Icmp(l) => l.summary(buf),
360            Self::Icmpv6(l) => l.summary(buf),
361            Self::Tcp(l) => l.summary(buf),
362            Self::Udp(l) => l.summary(buf),
363            Self::Dns(l) => l.summary(buf),
364            Self::Ssh(l) => l.summary(buf),
365            Self::Tls(l) => l.summary(buf),
366            Self::Dot15d4(l) => l.summary(buf),
367            Self::Dot15d4Fcs(l) => l.summary(buf),
368            Self::Dot11(l) => l.summary(buf),
369            Self::Http(l) => l.summary(buf),
370            Self::Http2(l) => l.summary(buf),
371            Self::Quic(l) => l.summary(buf),
372            Self::L2tp(l) => l.summary(buf),
373            Self::Raw(l) => l.summary(buf),
374        }
375    }
376
377    pub fn hashret(&self, buf: &[u8]) -> Vec<u8> {
378        match self {
379            Self::Ethernet(l) => l.hashret(buf),
380            Self::Arp(l) => l.hashret(buf),
381            Self::Ipv4(l) => l.hashret(buf),
382            Self::Icmp(l) => l.hashret(buf),
383            Self::Tcp(l) => l.hashret(buf),
384            Self::Udp(l) => l.hashret(buf),
385            Self::Dot15d4(l) => l.hashret(buf),
386            Self::Dot15d4Fcs(l) => l.hashret(buf),
387            Self::Dot11(l) => l.hashret(buf),
388            _ => vec![],
389        }
390    }
391
392    pub fn header_len(&self, buf: &[u8]) -> usize {
393        match self {
394            Self::Ethernet(l) => l.header_len(buf),
395            Self::Dot3(_) => ethernet::ETHERNET_HEADER_LEN,
396            Self::Arp(l) => l.header_len(buf),
397            Self::Ipv4(l) => l.header_len(buf),
398            Self::Ipv6(l) => l.header_len(buf),
399            Self::Icmp(l) => l.header_len(buf),
400            Self::Icmpv6(l) => l.header_len(buf),
401            Self::Tcp(l) => l.header_len(buf),
402            Self::Udp(l) => l.header_len(buf),
403            Self::Dns(l) => l.header_len(buf),
404            Self::Ssh(l) => l.header_len(buf),
405            Self::Tls(l) => l.header_len(buf),
406            Self::Dot15d4(l) => l.header_len(buf),
407            Self::Dot15d4Fcs(l) => l.header_len(buf),
408            Self::Dot11(l) => l.header_len(buf),
409            Self::Http(l) => l.header_len(buf),
410            Self::Http2(l) => l.header_len(buf),
411            Self::Quic(l) => l.header_len(buf),
412            Self::L2tp(l) => l.header_len(buf),
413            Self::Raw(l) => l.header_len(buf),
414        }
415    }
416
417    /// Returns a detailed field-by-field representation for show() output.
418    /// Format: Vec<(field_name, field_value)>
419    pub fn show_fields(&self, buf: &[u8]) -> Vec<(&'static str, String)> {
420        match self {
421            Self::Ethernet(l) => ethernet_show_fields(l, buf),
422            Self::Dot3(l) => dot3_show_fields(l, buf),
423            Self::Arp(l) => arp_show_fields(l, buf),
424            Self::Ipv4(l) => ipv4_show_fields(l, buf),
425            Self::Ipv6(l) => ipv6_show_fields(l, buf),
426            Self::Icmp(l) => icmp_show_fields(l, buf),
427            Self::Icmpv6(l) => icmpv6_show_fields(l, buf),
428            Self::Tcp(l) => tcp_show_fields(l, buf),
429            Self::Udp(l) => udp_show_fields(l, buf),
430            Self::Dns(l) => dns_show_fields(l, buf),
431            Self::Ssh(l) => ssh_show_fields(l, buf),
432            Self::Tls(l) => tls_show_fields(l, buf),
433            Self::Dot15d4(l) => dot15d4_show_fields(l, buf),
434            Self::Dot15d4Fcs(l) => dot15d4_fcs_show_fields(l, buf),
435            Self::Dot11(l) => dot11_show_fields(l, buf),
436            Self::Http(l) => http_show_fields(l, buf),
437            Self::Http2(l) => http2_show_fields(l, buf),
438            Self::Quic(l) => quic_show_fields(l, buf),
439            Self::L2tp(l) => l2tp_show_fields(l, buf),
440            Self::Raw(l) => raw::raw_show_fields(l, buf),
441        }
442    }
443
444    /// Get a field value by name from this layer.
445    /// Returns None if the field doesn't exist in this layer type.
446    pub fn get_field(&self, buf: &[u8], name: &str) -> Option<Result<FieldValue, FieldError>> {
447        match self {
448            Self::Ethernet(l) => l.get_field(buf, name),
449            Self::Dot3(l) => l.get_field(buf, name),
450            Self::Arp(l) => l.get_field(buf, name),
451            Self::Ipv4(l) => l.get_field(buf, name),
452            Self::Icmp(l) => l.get_field(buf, name),
453            Self::Tcp(l) => l.get_field(buf, name),
454            Self::Udp(l) => l.get_field(buf, name),
455            Self::Raw(l) => l.get_field(buf, name),
456            Self::Ssh(l) => l.get_field(buf, name),
457            Self::Tls(l) => l.get_field(buf, name),
458            Self::Dns(l) => l.get_field(buf, name),
459            Self::Dot15d4(l) => l.get_field(buf, name),
460            Self::Dot15d4Fcs(l) => l.get_field(buf, name),
461            Self::Dot11(l) => l.get_field(buf, name),
462            Self::Http(l) => l.get_field(buf, name),
463            Self::Http2(l) => l.get_field(buf, name),
464            Self::Quic(l) => l.get_field(buf, name),
465            Self::Ipv6(l) => l.get_field(buf, name),
466            Self::Icmpv6(l) => l.get_field(buf, name),
467            Self::L2tp(l) => l.get_field(buf, name),
468        }
469    }
470
471    /// Set a field value by name in this layer.
472    /// Returns None if the field doesn't exist in this layer type.
473    pub fn set_field(
474        &self,
475        buf: &mut [u8],
476        name: &str,
477        value: FieldValue,
478    ) -> Option<Result<(), FieldError>> {
479        match self {
480            Self::Ethernet(l) => l.set_field(buf, name, value),
481            Self::Dot3(l) => l.set_field(buf, name, value),
482            Self::Arp(l) => l.set_field(buf, name, value),
483            Self::Ipv4(l) => l.set_field(buf, name, value),
484            Self::Icmp(l) => l.set_field(buf, name, value),
485            Self::Tcp(l) => l.set_field(buf, name, value),
486            Self::Udp(l) => l.set_field(buf, name, value),
487            Self::Raw(l) => l.set_field(buf, name, value),
488            Self::Ssh(l) => l.set_field(buf, name, value),
489            Self::Tls(l) => l.set_field(buf, name, value),
490            Self::Dns(l) => l.set_field(buf, name, value),
491            Self::Dot15d4(l) => l.set_field(buf, name, value),
492            Self::Dot15d4Fcs(l) => l.set_field(buf, name, value),
493            Self::Dot11(l) => l.set_field(buf, name, value),
494            Self::Http(_) => None, // HTTP fields are read-only (text protocol)
495            Self::Http2(_) => None, // HTTP/2 fields are read-only via this interface
496            Self::Quic(l) => l.set_field(buf, name, value),
497            Self::Ipv6(l) => l.set_field(buf, name, value),
498            Self::Icmpv6(l) => l.set_field(buf, name, value),
499            Self::L2tp(l) => l.set_field(buf, name, value),
500        }
501    }
502
503    /// Get the list of field names for this layer type.
504    pub fn field_names(&self) -> &'static [&'static str] {
505        match self {
506            Self::Ethernet(l) => l.field_names(),
507            Self::Dot3(_) => Dot3Layer::field_names(),
508            Self::Arp(l) => l.field_names(),
509            Self::Ipv4(l) => l.field_names(),
510            Self::Icmp(l) => l.field_names(),
511            Self::Tcp(l) => l.field_names(),
512            Self::Udp(l) => l.field_names(),
513            Self::Raw(_) => RawLayer::field_names(),
514            Self::Ssh(l) => l.field_names(),
515            Self::Tls(l) => l.field_names(),
516            Self::Dns(_) => DnsLayer::field_names(),
517            Self::Dot15d4(_) => dot15d4::Dot15d4Layer::field_names(),
518            Self::Dot15d4Fcs(_) => dot15d4::Dot15d4FcsLayer::field_names(),
519            Self::Dot11(_) => dot11::Dot11Layer::field_names(),
520            Self::Http(l) => l.field_names(),
521            Self::Http2(_) => Http2Layer::field_names(),
522            Self::Quic(_) => quic::QuicLayer::field_names(),
523            Self::Ipv6(_) => Ipv6Layer::field_names(),
524            Self::Icmpv6(_) => Icmpv6Layer::field_names(),
525            Self::L2tp(_) => l2tp::L2tpLayer::field_names(),
526        }
527    }
528}
529
530// ============================================================================
531// Show Fields Implementations
532// ============================================================================
533
534fn ethernet_show_fields(l: &EthernetLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
535    let mut fields = Vec::new();
536    fields.push((
537        "dst",
538        l.dst(buf)
539            .map(|m| m.to_string())
540            .unwrap_or_else(|_| "?".into()),
541    ));
542    fields.push((
543        "src",
544        l.src(buf)
545            .map(|m| m.to_string())
546            .unwrap_or_else(|_| "?".into()),
547    ));
548    let etype = l.ethertype(buf).unwrap_or(0);
549    fields.push((
550        "type",
551        format!("{:#06x} ({})", etype, ethertype::name(etype)),
552    ));
553    fields
554}
555
556fn dot3_show_fields(l: &Dot3Layer, buf: &[u8]) -> Vec<(&'static str, String)> {
557    let mut fields = Vec::new();
558    fields.push((
559        "dst",
560        l.dst(buf)
561            .map(|m| m.to_string())
562            .unwrap_or_else(|_| "?".into()),
563    ));
564    fields.push((
565        "src",
566        l.src(buf)
567            .map(|m| m.to_string())
568            .unwrap_or_else(|_| "?".into()),
569    ));
570    fields.push((
571        "len",
572        l.len_field(buf)
573            .map(|v| v.to_string())
574            .unwrap_or_else(|_| "?".into()),
575    ));
576    fields
577}
578
579fn arp_show_fields(l: &ArpLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
580    let mut fields = Vec::new();
581    let hwtype = l.hwtype(buf).unwrap_or(0);
582    fields.push((
583        "hwtype",
584        format!("{:#06x} ({})", hwtype, arp::hardware_type::name(hwtype)),
585    ));
586    let ptype = l.ptype(buf).unwrap_or(0);
587    fields.push(("ptype", format!("{:#06x}", ptype)));
588    fields.push((
589        "hwlen",
590        l.hwlen(buf)
591            .map(|v| v.to_string())
592            .unwrap_or_else(|_| "?".into()),
593    ));
594    fields.push((
595        "plen",
596        l.plen(buf)
597            .map(|v| v.to_string())
598            .unwrap_or_else(|_| "?".into()),
599    ));
600    let op = l.op(buf).unwrap_or(0);
601    fields.push(("op", format!("{} ({})", op, arp::opcode::name(op))));
602    fields.push((
603        "hwsrc",
604        l.hwsrc_raw(buf)
605            .map(|a| a.to_string())
606            .unwrap_or_else(|_| "?".into()),
607    ));
608    fields.push((
609        "psrc",
610        l.psrc_raw(buf)
611            .map(|a| a.to_string())
612            .unwrap_or_else(|_| "?".into()),
613    ));
614    fields.push((
615        "hwdst",
616        l.hwdst_raw(buf)
617            .map(|a| a.to_string())
618            .unwrap_or_else(|_| "?".into()),
619    ));
620    fields.push((
621        "pdst",
622        l.pdst_raw(buf)
623            .map(|a| a.to_string())
624            .unwrap_or_else(|_| "?".into()),
625    ));
626    fields
627}
628
629fn ipv4_show_fields(l: &Ipv4Layer, buf: &[u8]) -> Vec<(&'static str, String)> {
630    let mut fields = Vec::new();
631    fields.push((
632        "version",
633        l.version(buf)
634            .map(|v| v.to_string())
635            .unwrap_or_else(|_| "?".into()),
636    ));
637    fields.push((
638        "ihl",
639        l.ihl(buf)
640            .map(|v| v.to_string())
641            .unwrap_or_else(|_| "?".into()),
642    ));
643    fields.push((
644        "tos",
645        l.tos(buf)
646            .map(|v| format!("{:#04x}", v))
647            .unwrap_or_else(|_| "?".into()),
648    ));
649    fields.push((
650        "len",
651        l.total_len(buf)
652            .map(|v| v.to_string())
653            .unwrap_or_else(|_| "?".into()),
654    ));
655    fields.push((
656        "id",
657        l.id(buf)
658            .map(|v| format!("{:#06x}", v))
659            .unwrap_or_else(|_| "?".into()),
660    ));
661    fields.push((
662        "flags",
663        l.flags(buf)
664            .map(|f| f.to_string())
665            .unwrap_or_else(|_| "?".into()),
666    ));
667    fields.push((
668        "frag",
669        l.frag_offset(buf)
670            .map(|v| v.to_string())
671            .unwrap_or_else(|_| "?".into()),
672    ));
673    fields.push((
674        "ttl",
675        l.ttl(buf)
676            .map(|v| v.to_string())
677            .unwrap_or_else(|_| "?".into()),
678    ));
679    let proto = l.protocol(buf).unwrap_or(0);
680    fields.push(("proto", format!("{} ({})", proto, l.protocol_name(buf))));
681    fields.push((
682        "chksum",
683        l.checksum(buf)
684            .map(|v| format!("{:#06x}", v))
685            .unwrap_or_else(|_| "?".into()),
686    ));
687    fields.push((
688        "src",
689        l.src(buf)
690            .map(|ip| ip.to_string())
691            .unwrap_or_else(|_| "?".into()),
692    ));
693    fields.push((
694        "dst",
695        l.dst(buf)
696            .map(|ip| ip.to_string())
697            .unwrap_or_else(|_| "?".into()),
698    ));
699    // Options (if present)
700    let opts_len = l.options_len(buf);
701    if opts_len > 0 {
702        fields.push(("options", format!("[{} bytes]", opts_len)));
703    }
704    fields
705}
706
707fn ipv6_show_fields(l: &Ipv6Layer, buf: &[u8]) -> Vec<(&'static str, String)> {
708    let mut fields = Vec::new();
709    fields.push((
710        "version",
711        l.version(buf)
712            .map(|v| v.to_string())
713            .unwrap_or_else(|_| "?".into()),
714    ));
715    fields.push((
716        "tc",
717        l.traffic_class(buf)
718            .map(|v| format!("{:#04x}", v))
719            .unwrap_or_else(|_| "?".into()),
720    ));
721    fields.push((
722        "fl",
723        l.flow_label(buf)
724            .map(|v| format!("{:#07x}", v))
725            .unwrap_or_else(|_| "?".into()),
726    ));
727    fields.push((
728        "plen",
729        l.payload_len(buf)
730            .map(|v| v.to_string())
731            .unwrap_or_else(|_| "?".into()),
732    ));
733    let nh = l.next_header(buf).unwrap_or(0);
734    fields.push(("nh", format!("{} ({})", nh, ipv4::protocol::to_name(nh))));
735    fields.push((
736        "hlim",
737        l.hop_limit(buf)
738            .map(|v| v.to_string())
739            .unwrap_or_else(|_| "?".into()),
740    ));
741    fields.push((
742        "src",
743        l.src(buf)
744            .map(|a| a.to_string())
745            .unwrap_or_else(|_| "?".into()),
746    ));
747    fields.push((
748        "dst",
749        l.dst(buf)
750            .map(|a| a.to_string())
751            .unwrap_or_else(|_| "?".into()),
752    ));
753    fields
754}
755
756fn icmp_show_fields(l: &IcmpLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
757    let mut fields = Vec::new();
758
759    // Type field
760    fields.push((
761        "type",
762        l.icmp_type(buf)
763            .map(|t: u8| format!("{} ({})", t, icmp::type_name(t)))
764            .unwrap_or_else(|_| "?".into()),
765    ));
766
767    // Code field
768    fields.push((
769        "code",
770        l.code(buf)
771            .map(|c: u8| c.to_string())
772            .unwrap_or_else(|_| "?".into()),
773    ));
774
775    // Checksum field
776    fields.push((
777        "chksum",
778        l.checksum(buf)
779            .map(|v: u16| format!("{:#06x}", v))
780            .unwrap_or_else(|_| "?".into()),
781    ));
782
783    // ID field (conditional)
784    if let Ok(Some(id)) = l.id(buf) {
785        fields.push(("id", format!("{:#06x}", id)));
786    }
787
788    // Sequence field (conditional)
789    if let Ok(Some(seq)) = l.seq(buf) {
790        fields.push(("seq", seq.to_string()));
791    }
792
793    // Gateway field (for redirect)
794    if let Ok(Some(gateway)) = l.gateway(buf) {
795        fields.push(("gw", gateway.to_string()));
796    }
797
798    // Pointer field (for parameter problem)
799    if let Ok(Some(ptr)) = l.ptr(buf) {
800        fields.push(("ptr", ptr.to_string()));
801    }
802
803    // Next-hop MTU (for dest unreachable, fragmentation needed)
804    if let Ok(Some(mtu)) = l.next_hop_mtu(buf) {
805        fields.push(("mtu", mtu.to_string()));
806    }
807
808    // Timestamp fields (for timestamp request/reply)
809    if let Ok(Some(ts_ori)) = l.ts_ori(buf) {
810        fields.push(("ts_ori", ts_ori.to_string()));
811    }
812    if let Ok(Some(ts_rx)) = l.ts_rx(buf) {
813        fields.push(("ts_rx", ts_rx.to_string()));
814    }
815    if let Ok(Some(ts_tx)) = l.ts_tx(buf) {
816        fields.push(("ts_tx", ts_tx.to_string()));
817    }
818
819    // Address mask (for address mask request/reply)
820    if let Ok(Some(addr_mask)) = l.addr_mask(buf) {
821        fields.push(("addr_mask", addr_mask.to_string()));
822    }
823
824    fields
825}
826
827fn icmpv6_show_fields(l: &Icmpv6Layer, buf: &[u8]) -> Vec<(&'static str, String)> {
828    let mut fields = Vec::new();
829    let icmpv6_type = l.icmpv6_type(buf).unwrap_or(0);
830    let type_name = icmpv6::types::name(icmpv6_type);
831    fields.push(("type", format!("{} ({})", icmpv6_type, type_name)));
832    fields.push((
833        "code",
834        l.code(buf)
835            .map(|v| v.to_string())
836            .unwrap_or_else(|_| "?".into()),
837    ));
838    fields.push((
839        "chksum",
840        l.checksum(buf)
841            .map(|v| format!("{:#06x}", v))
842            .unwrap_or_else(|_| "?".into()),
843    ));
844    if let Ok(Some(id)) = l.id(buf) {
845        fields.push(("id", format!("{:#06x}", id)));
846    }
847    if let Ok(Some(seq)) = l.seq(buf) {
848        fields.push(("seq", seq.to_string()));
849    }
850    if let Ok(Some(target)) = l.target_addr(buf) {
851        fields.push(("tgt", target.to_string()));
852    }
853    if let Ok(Some(mtu)) = l.mtu(buf) {
854        fields.push(("mtu", mtu.to_string()));
855    }
856    fields
857}
858
859fn tcp_show_fields(l: &TcpLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
860    let mut fields = Vec::new();
861    fields.push((
862        "sport",
863        l.src_port(buf)
864            .map(|v| v.to_string())
865            .unwrap_or_else(|_| "?".into()),
866    ));
867    fields.push((
868        "dport",
869        l.dst_port(buf)
870            .map(|v| v.to_string())
871            .unwrap_or_else(|_| "?".into()),
872    ));
873    fields.push((
874        "seq",
875        l.seq(buf)
876            .map(|v| v.to_string())
877            .unwrap_or_else(|_| "?".into()),
878    ));
879    fields.push((
880        "ack",
881        l.ack(buf)
882            .map(|v| v.to_string())
883            .unwrap_or_else(|_| "?".into()),
884    ));
885    fields.push((
886        "dataofs",
887        l.data_offset(buf)
888            .map(|v| v.to_string())
889            .unwrap_or_else(|_| "?".into()),
890    ));
891    fields.push((
892        "reserved",
893        l.reserved(buf)
894            .map(|v| v.to_string())
895            .unwrap_or_else(|_| "?".into()),
896    ));
897    fields.push((
898        "flags",
899        l.flags(buf)
900            .map(|f| f.to_string())
901            .unwrap_or_else(|_| "?".into()),
902    ));
903    fields.push((
904        "window",
905        l.window(buf)
906            .map(|v| v.to_string())
907            .unwrap_or_else(|_| "?".into()),
908    ));
909    fields.push((
910        "chksum",
911        l.checksum(buf)
912            .map(|v| format!("{:#06x}", v))
913            .unwrap_or_else(|_| "?".into()),
914    ));
915    fields.push((
916        "urgptr",
917        l.urgent_ptr(buf)
918            .map(|v| v.to_string())
919            .unwrap_or_else(|_| "?".into()),
920    ));
921    // Options (if present)
922    let opts_len = l.options_len(buf);
923    if opts_len > 0 {
924        fields.push(("options", format!("[{} bytes]", opts_len)));
925    }
926    fields
927}
928
929fn udp_show_fields(l: &UdpLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
930    let mut fields = Vec::new();
931    fields.push((
932        "sport",
933        l.src_port(buf)
934            .map(|v: u16| v.to_string())
935            .unwrap_or_else(|_| "?".into()),
936    ));
937    fields.push((
938        "dport",
939        l.dst_port(buf)
940            .map(|v: u16| v.to_string())
941            .unwrap_or_else(|_| "?".into()),
942    ));
943    fields.push((
944        "len",
945        l.length(buf)
946            .map(|v: u16| v.to_string())
947            .unwrap_or_else(|_| "?".into()),
948    ));
949    fields.push((
950        "chksum",
951        l.checksum(buf)
952            .map(|v: u16| format!("{:#06x}", v))
953            .unwrap_or_else(|_| "?".into()),
954    ));
955    fields
956}
957
958fn dns_show_fields(l: &DnsLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
959    let mut fields = Vec::new();
960    fields.push((
961        "id",
962        l.id(buf)
963            .map(|v| format!("{:#06x}", v))
964            .unwrap_or_else(|_| "?".into()),
965    ));
966    let qr = l.qr(buf).unwrap_or(false);
967    fields.push(("qr", if qr { "response" } else { "query" }.to_string()));
968    fields.push((
969        "opcode",
970        l.opcode(buf)
971            .map(|v| format!("{} ({})", v, dns::types::opcode_name(v)))
972            .unwrap_or_else(|_| "?".into()),
973    ));
974    fields.push((
975        "aa",
976        l.aa(buf)
977            .map(|v| v.to_string())
978            .unwrap_or_else(|_| "?".into()),
979    ));
980    fields.push((
981        "tc",
982        l.tc(buf)
983            .map(|v| v.to_string())
984            .unwrap_or_else(|_| "?".into()),
985    ));
986    fields.push((
987        "rd",
988        l.rd(buf)
989            .map(|v| v.to_string())
990            .unwrap_or_else(|_| "?".into()),
991    ));
992    fields.push((
993        "ra",
994        l.ra(buf)
995            .map(|v| v.to_string())
996            .unwrap_or_else(|_| "?".into()),
997    ));
998    fields.push((
999        "z",
1000        l.z(buf)
1001            .map(|v| v.to_string())
1002            .unwrap_or_else(|_| "?".into()),
1003    ));
1004    fields.push((
1005        "ad",
1006        l.ad(buf)
1007            .map(|v| v.to_string())
1008            .unwrap_or_else(|_| "?".into()),
1009    ));
1010    fields.push((
1011        "cd",
1012        l.cd(buf)
1013            .map(|v| v.to_string())
1014            .unwrap_or_else(|_| "?".into()),
1015    ));
1016    fields.push((
1017        "rcode",
1018        l.rcode(buf)
1019            .map(|v| format!("{} ({})", v, dns::types::rcode_name(v)))
1020            .unwrap_or_else(|_| "?".into()),
1021    ));
1022    fields.push((
1023        "qdcount",
1024        l.qdcount(buf)
1025            .map(|v| v.to_string())
1026            .unwrap_or_else(|_| "?".into()),
1027    ));
1028    fields.push((
1029        "ancount",
1030        l.ancount(buf)
1031            .map(|v| v.to_string())
1032            .unwrap_or_else(|_| "?".into()),
1033    ));
1034    fields.push((
1035        "nscount",
1036        l.nscount(buf)
1037            .map(|v| v.to_string())
1038            .unwrap_or_else(|_| "?".into()),
1039    ));
1040    fields.push((
1041        "arcount",
1042        l.arcount(buf)
1043            .map(|v| v.to_string())
1044            .unwrap_or_else(|_| "?".into()),
1045    ));
1046    // Show questions if present
1047    if let Ok(questions) = l.questions(buf) {
1048        for (i, q) in questions.iter().enumerate() {
1049            fields.push(("qd", format!("[{}] {}", i, q.summary())));
1050        }
1051    }
1052    fields
1053}
1054
1055fn ssh_show_fields(l: &SshLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
1056    let mut fields = Vec::new();
1057    if l.is_version_exchange(buf) {
1058        if let Some(vs) = l.version_string(buf) {
1059            fields.push(("version_string", vs.to_string()));
1060        }
1061    } else {
1062        fields.push((
1063            "packet_length",
1064            l.packet_length(buf)
1065                .map(|v| v.to_string())
1066                .unwrap_or_else(|_| "?".into()),
1067        ));
1068        fields.push((
1069            "padding_length",
1070            l.padding_length(buf)
1071                .map(|v| v.to_string())
1072                .unwrap_or_else(|_| "?".into()),
1073        ));
1074        match l.message_type(buf) {
1075            Ok(Some(t)) => {
1076                fields.push((
1077                    "message_type",
1078                    format!("{} ({})", t, ssh::msg_types::name(t)),
1079                ));
1080            }
1081            Ok(None) => {}
1082            Err(_) => {
1083                fields.push(("message_type", "?".into()));
1084            }
1085        }
1086    }
1087    fields
1088}
1089
1090fn tls_show_fields(l: &TlsLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
1091    let mut fields = Vec::new();
1092    fields.push((
1093        "type",
1094        l.content_type(buf)
1095            .map(|ct| format!("{} ({})", ct.as_u8(), ct.name()))
1096            .unwrap_or_else(|_| "?".into()),
1097    ));
1098    fields.push((
1099        "version",
1100        l.version(buf)
1101            .map(|v| {
1102                let ver = TlsVersion(v);
1103                format!("{:#06x} ({})", v, ver.name())
1104            })
1105            .unwrap_or_else(|_| "?".into()),
1106    ));
1107    fields.push((
1108        "len",
1109        l.length(buf)
1110            .map(|v| v.to_string())
1111            .unwrap_or_else(|_| "?".into()),
1112    ));
1113    let frag = l.fragment(buf);
1114    if !frag.is_empty() {
1115        if frag.len() <= 16 {
1116            fields.push(("fragment", format!("[{} bytes] {:02x?}", frag.len(), frag)));
1117        } else {
1118            fields.push(("fragment", format!("[{} bytes]", frag.len())));
1119        }
1120    }
1121    fields
1122}
1123
1124fn dot11_show_fields(l: &dot11::Dot11Layer, buf: &[u8]) -> Vec<(&'static str, String)> {
1125    let mut fields = Vec::new();
1126    fields.push((
1127        "type",
1128        l.frame_type(buf)
1129            .map(|v| format!("{} ({})", v, dot11::types::frame_type::name(v)))
1130            .unwrap_or_else(|_| "?".into()),
1131    ));
1132    fields.push((
1133        "subtype",
1134        l.subtype(buf)
1135            .map(|v| {
1136                let ft = l.frame_type(buf).unwrap_or(0);
1137                format!("{} ({})", v, dot11::types::subtype_name(ft, v))
1138            })
1139            .unwrap_or_else(|_| "?".into()),
1140    ));
1141    fields.push((
1142        "proto",
1143        l.protocol_version(buf)
1144            .map(|v| v.to_string())
1145            .unwrap_or_else(|_| "?".into()),
1146    ));
1147    fields.push((
1148        "FCfield",
1149        l.flags(buf)
1150            .map(|v| format!("{:#04x}", v))
1151            .unwrap_or_else(|_| "?".into()),
1152    ));
1153    fields.push((
1154        "ID",
1155        l.duration(buf)
1156            .map(|v| v.to_string())
1157            .unwrap_or_else(|_| "?".into()),
1158    ));
1159    fields.push((
1160        "addr1",
1161        l.addr1(buf)
1162            .map(|v| v.to_string())
1163            .unwrap_or_else(|_| "?".into()),
1164    ));
1165    fields.push((
1166        "addr2",
1167        l.addr2(buf)
1168            .map(|v| v.to_string())
1169            .unwrap_or_else(|_| "?".into()),
1170    ));
1171    fields.push((
1172        "addr3",
1173        l.addr3(buf)
1174            .map(|v| v.to_string())
1175            .unwrap_or_else(|_| "?".into()),
1176    ));
1177    fields.push((
1178        "SC",
1179        l.seq_ctrl_raw(buf)
1180            .map(|v| format!("{:#06x}", v))
1181            .unwrap_or_else(|_| "?".into()),
1182    ));
1183    if l.has_addr4(buf) {
1184        fields.push((
1185            "addr4",
1186            l.addr4(buf)
1187                .map(|v| v.to_string())
1188                .unwrap_or_else(|_| "?".into()),
1189        ));
1190    }
1191    fields
1192}
1193
1194fn dot15d4_show_fields(l: &dot15d4::Dot15d4Layer, buf: &[u8]) -> Vec<(&'static str, String)> {
1195    let mut fields = Vec::new();
1196    // Frame type with name
1197    let ft = l.fcf_frametype(buf).unwrap_or(0);
1198    fields.push((
1199        "fcf_frametype",
1200        format!("{} ({})", ft, dot15d4::types::frame_type_name(ft)),
1201    ));
1202    // FCF flags
1203    fields.push((
1204        "fcf_security",
1205        l.fcf_security(buf)
1206            .map(|v| v.to_string())
1207            .unwrap_or_else(|_| "?".into()),
1208    ));
1209    fields.push((
1210        "fcf_pending",
1211        l.fcf_pending(buf)
1212            .map(|v| v.to_string())
1213            .unwrap_or_else(|_| "?".into()),
1214    ));
1215    fields.push((
1216        "fcf_ackreq",
1217        l.fcf_ackreq(buf)
1218            .map(|v| v.to_string())
1219            .unwrap_or_else(|_| "?".into()),
1220    ));
1221    fields.push((
1222        "fcf_panidcompress",
1223        l.fcf_panidcompress(buf)
1224            .map(|v| v.to_string())
1225            .unwrap_or_else(|_| "?".into()),
1226    ));
1227    // Address modes with names
1228    let dam = l.fcf_destaddrmode(buf).unwrap_or(0);
1229    fields.push((
1230        "fcf_destaddrmode",
1231        format!("{} ({})", dam, dot15d4::types::addr_mode_name(dam)),
1232    ));
1233    fields.push((
1234        "fcf_framever",
1235        l.fcf_framever(buf)
1236            .map(|v| v.to_string())
1237            .unwrap_or_else(|_| "?".into()),
1238    ));
1239    let sam = l.fcf_srcaddrmode(buf).unwrap_or(0);
1240    fields.push((
1241        "fcf_srcaddrmode",
1242        format!("{} ({})", sam, dot15d4::types::addr_mode_name(sam)),
1243    ));
1244    // Sequence number
1245    fields.push((
1246        "seqnum",
1247        l.seqnum(buf)
1248            .map(|v| v.to_string())
1249            .unwrap_or_else(|_| "?".into()),
1250    ));
1251    // Conditional addressing fields
1252    if let Ok(Some(panid)) = l.dest_panid(buf) {
1253        fields.push(("dest_panid", format!("{:#06x}", panid)));
1254    }
1255    if let Ok(Some(addr)) = l.dest_addr_short(buf) {
1256        fields.push(("dest_addr", format!("{:#06x}", addr)));
1257    }
1258    if let Ok(Some(addr)) = l.dest_addr_long(buf) {
1259        fields.push(("dest_addr", format!("{:#018x}", addr)));
1260    }
1261    if let Ok(Some(panid)) = l.src_panid(buf) {
1262        fields.push(("src_panid", format!("{:#06x}", panid)));
1263    }
1264    if let Ok(Some(addr)) = l.src_addr_short(buf) {
1265        fields.push(("src_addr", format!("{:#06x}", addr)));
1266    }
1267    if let Ok(Some(addr)) = l.src_addr_long(buf) {
1268        fields.push(("src_addr", format!("{:#018x}", addr)));
1269    }
1270    fields
1271}
1272
1273fn dot15d4_fcs_show_fields(
1274    l: &dot15d4::Dot15d4FcsLayer,
1275    buf: &[u8],
1276) -> Vec<(&'static str, String)> {
1277    let inner = dot15d4::Dot15d4Layer::new(l.index.start, l.index.end.saturating_sub(2));
1278    let mut fields = dot15d4_show_fields(&inner, buf);
1279    // Show FCS with verification status
1280    let slice = l.index.slice(buf);
1281    if slice.len() >= 2 {
1282        let fcs_bytes = &slice[slice.len() - 2..];
1283        let fcs = u16::from_le_bytes([fcs_bytes[0], fcs_bytes[1]]);
1284        let verified = l.verify_fcs(buf).unwrap_or(false);
1285        let status = if verified { "ok" } else { "INVALID" };
1286        fields.push(("fcs", format!("{:#06x} ({})", fcs, status)));
1287    }
1288    fields
1289}
1290
1291fn http_show_fields(l: &http::HttpLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
1292    let mut fields = Vec::new();
1293    if l.is_request(buf) {
1294        fields.push(("method", l.method(buf).unwrap_or("?").to_string()));
1295        fields.push(("uri", l.uri(buf).unwrap_or("?").to_string()));
1296        fields.push(("version", l.http_version(buf).unwrap_or("?").to_string()));
1297    } else if l.is_response(buf) {
1298        fields.push(("version", l.http_version(buf).unwrap_or("?").to_string()));
1299        fields.push((
1300            "status_code",
1301            l.status_code(buf)
1302                .map(|c| c.to_string())
1303                .unwrap_or_else(|| "?".into()),
1304        ));
1305        fields.push(("reason", l.reason(buf).unwrap_or("?").to_string()));
1306    }
1307    fields
1308}
1309
1310fn http2_show_fields(l: &http2::Http2Layer, buf: &[u8]) -> Vec<(&'static str, String)> {
1311    let mut fields = Vec::new();
1312    if l.has_preface {
1313        fields.push(("preface", "true".to_string()));
1314    }
1315    if let Some(frame) = l.first_frame(buf) {
1316        fields.push((
1317            "frame_type",
1318            format!("{} ({})", frame.frame_type.as_u8(), frame.frame_type.name()),
1319        ));
1320        fields.push(("flags", format!("{:#04x}", frame.flags)));
1321        fields.push(("stream_id", frame.stream_id.to_string()));
1322        fields.push(("length", frame.length.to_string()));
1323    }
1324    fields
1325}
1326
1327fn quic_show_fields(l: &quic::QuicLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
1328    let mut fields = Vec::new();
1329    fields.push((
1330        "header_form",
1331        if l.is_long_header(buf) {
1332            "long".to_string()
1333        } else {
1334            "short".to_string()
1335        },
1336    ));
1337    if let Some(pt) = l.packet_type(buf) {
1338        fields.push(("packet_type", pt.name().to_string()));
1339    }
1340    if let Some(ver) = l.version(buf) {
1341        fields.push(("version", format!("{:#010x}", ver)));
1342    }
1343    fields
1344}
1345
1346fn l2tp_show_fields(l: &l2tp::L2tpLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
1347    let mut fields = Vec::new();
1348    fields.push((
1349        "flags",
1350        l.flags_word(buf)
1351            .map(|v| format!("{:#06x}", v))
1352            .unwrap_or_else(|_| "?".into()),
1353    ));
1354    fields.push((
1355        "version",
1356        l.version(buf)
1357            .map(|v| v.to_string())
1358            .unwrap_or_else(|_| "?".into()),
1359    ));
1360    fields.push((
1361        "msg_type",
1362        l.msg_type(buf)
1363            .map(|v| {
1364                if v == 0 {
1365                    "data".to_string()
1366                } else {
1367                    "control".to_string()
1368                }
1369            })
1370            .unwrap_or_else(|_| "?".into()),
1371    ));
1372    if let Ok(Some(length)) = l.length(buf) {
1373        fields.push(("length", length.to_string()));
1374    }
1375    fields.push((
1376        "tunnel_id",
1377        l.tunnel_id(buf)
1378            .map(|v| v.to_string())
1379            .unwrap_or_else(|_| "?".into()),
1380    ));
1381    fields.push((
1382        "session_id",
1383        l.session_id(buf)
1384            .map(|v| v.to_string())
1385            .unwrap_or_else(|_| "?".into()),
1386    ));
1387    if let Ok(Some(ns)) = l.ns(buf) {
1388        fields.push(("ns", ns.to_string()));
1389    }
1390    if let Ok(Some(nr)) = l.nr(buf) {
1391        fields.push(("nr", nr.to_string()));
1392    }
1393    fields
1394}
1395
1396// DnsLayer is now in dns::DnsLayer
1397pub use dns::DnsLayer;
1398
1399/// EtherType constants
1400pub mod ethertype {
1401    use crate::LayerKind;
1402
1403    pub const IPV4: u16 = 0x0800;
1404    pub const ARP: u16 = 0x0806;
1405    pub const IPV6: u16 = 0x86DD;
1406    pub const VLAN: u16 = 0x8100;
1407    pub const DOT1AD: u16 = 0x88A8;
1408    pub const DOT1AH: u16 = 0x88E7;
1409    pub const MACSEC: u16 = 0x88E5;
1410    pub const LOOPBACK: u16 = 0x9000;
1411
1412    pub fn name(t: u16) -> &'static str {
1413        match t {
1414            IPV4 => "IPv4",
1415            ARP => "ARP",
1416            IPV6 => "IPv6",
1417            VLAN => "802.1Q",
1418            DOT1AD => "802.1AD",
1419            DOT1AH => "802.1AH",
1420            MACSEC => "MACsec",
1421            LOOPBACK => "Loopback",
1422            _ => "Unknown",
1423        }
1424    }
1425
1426    pub fn to_layer_kind(t: u16) -> Option<LayerKind> {
1427        match t {
1428            IPV4 => Some(LayerKind::Ipv4),
1429            ARP => Some(LayerKind::Arp),
1430            IPV6 => Some(LayerKind::Ipv6),
1431            VLAN => Some(LayerKind::Dot1Q),
1432            DOT1AD => Some(LayerKind::Dot1AD),
1433            DOT1AH => Some(LayerKind::Dot1AH),
1434            _ => None,
1435        }
1436    }
1437
1438    pub fn from_layer_kind(kind: LayerKind) -> Option<u16> {
1439        match kind {
1440            LayerKind::Ipv4 => Some(IPV4),
1441            LayerKind::Arp => Some(ARP),
1442            LayerKind::Ipv6 => Some(IPV6),
1443            LayerKind::Dot1Q => Some(VLAN),
1444            LayerKind::Dot1AD => Some(DOT1AD),
1445            LayerKind::Dot1AH => Some(DOT1AH),
1446            _ => None,
1447        }
1448    }
1449}
1450
1451/// IP protocol numbers
1452pub mod ip_protocol {
1453    pub use crate::layer::ipv4::protocol::*;
1454}
1455
1456#[cfg(test)]
1457mod tests {
1458    use super::*;
1459
1460    #[test]
1461    fn test_layer_kind() {
1462        assert_eq!(LayerKind::Ethernet.name(), "Ethernet");
1463        assert_eq!(LayerKind::Arp.min_header_size(), 28);
1464        assert!(LayerKind::Ethernet.is_link_layer());
1465        assert!(LayerKind::Ipv4.is_network_layer());
1466        assert!(LayerKind::Tcp.is_transport_layer());
1467    }
1468
1469    #[test]
1470    fn test_layer_index() {
1471        let idx = LayerIndex::new(LayerKind::Ethernet, 0, 14);
1472        assert_eq!(idx.len(), 14);
1473        assert_eq!(idx.range(), 0..14);
1474
1475        let buf = vec![0u8; 100];
1476        assert_eq!(idx.slice(&buf).len(), 14);
1477        assert_eq!(idx.payload(&buf).len(), 86);
1478    }
1479
1480    #[test]
1481    fn test_ethertype_conversions() {
1482        assert_eq!(ethertype::to_layer_kind(0x0800), Some(LayerKind::Ipv4));
1483        assert_eq!(ethertype::from_layer_kind(LayerKind::Arp), Some(0x0806));
1484    }
1485}