1pub 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
33pub 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#[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, Self::Dot15d4Fcs => 5, Self::Dot11 => dot11::DOT11_MIN_HEADER_LEN,
151 Self::Http => 14, Self::Quic => quic::QUIC_MIN_HEADER_LEN,
153 Self::Generic => 0,
154 Self::Http2 => 9, Self::L2tp => l2tp::L2TP_MIN_HEADER_LEN,
156 Self::Raw => 0,
157 }
158 }
159
160 #[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 #[inline]
171 pub const fn is_network_layer(&self) -> bool {
172 matches!(self, Self::Ipv4 | Self::Ipv6 | Self::Arp)
173 }
174
175 #[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#[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 #[inline]
219 pub fn slice<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
220 &buf[self.start..self.end.min(buf.len())]
221 }
222
223 #[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 #[inline]
232 pub fn payload<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
233 &buf[self.end.min(buf.len())..]
234 }
235}
236
237pub trait Layer {
243 fn kind(&self) -> LayerKind;
245
246 fn summary(&self, data: &[u8]) -> String;
248
249 fn header_len(&self, data: &[u8]) -> usize;
251
252 fn hashret(&self, _data: &[u8]) -> Vec<u8> {
254 vec![]
255 }
256
257 fn answers(&self, _data: &[u8], _other: &Self, _other_data: &[u8]) -> bool {
259 false
260 }
261
262 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 fn field_names(&self) -> &'static [&'static str] {
270 &[]
271 }
272}
273
274#[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 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 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 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, Self::Http2(_) => None, 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 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
530fn 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 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 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 fields.push((
769 "code",
770 l.code(buf)
771 .map(|c: u8| c.to_string())
772 .unwrap_or_else(|_| "?".into()),
773 ));
774
775 fields.push((
777 "chksum",
778 l.checksum(buf)
779 .map(|v: u16| format!("{:#06x}", v))
780 .unwrap_or_else(|_| "?".into()),
781 ));
782
783 if let Ok(Some(id)) = l.id(buf) {
785 fields.push(("id", format!("{:#06x}", id)));
786 }
787
788 if let Ok(Some(seq)) = l.seq(buf) {
790 fields.push(("seq", seq.to_string()));
791 }
792
793 if let Ok(Some(gateway)) = l.gateway(buf) {
795 fields.push(("gw", gateway.to_string()));
796 }
797
798 if let Ok(Some(ptr)) = l.ptr(buf) {
800 fields.push(("ptr", ptr.to_string()));
801 }
802
803 if let Ok(Some(mtu)) = l.next_hop_mtu(buf) {
805 fields.push(("mtu", mtu.to_string()));
806 }
807
808 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 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 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 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 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 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 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 fields.push((
1246 "seqnum",
1247 l.seqnum(buf)
1248 .map(|v| v.to_string())
1249 .unwrap_or_else(|_| "?".into()),
1250 ));
1251 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 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
1396pub use dns::DnsLayer;
1398
1399pub 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
1451pub 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}