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