sniffnet_packet_parser/
headers.rs1use crate::igmp_type::IgmpType;
2use crate::link_type::LinkType;
3use crate::{ArpType, IcmpType, Protocol};
4use etherparse::{EtherType, LaxPacketHeaders};
5use std::net::IpAddr;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub struct LinkInfo {
10 pub src_mac: Option<[u8; 6]>,
12 pub dst_mac: Option<[u8; 6]>,
14 pub vlan_id: Option<u16>,
16 pub(crate) bytes: usize,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20pub struct NetInfo {
22 pub src_ip: IpAddr,
24 pub dst_ip: IpAddr,
26 pub arp_type: Option<ArpType>,
28 pub(crate) bytes: usize,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
32pub struct TransportInfo {
34 pub src_port: Option<u16>,
36 pub dst_port: Option<u16>,
38 pub protocol: Protocol,
40 pub icmp_type: Option<IcmpType>,
42 pub igmp_type: Option<IgmpType>,
44}
45
46#[must_use]
47pub(crate) fn get_sniffable_headers(
48 packet: &[u8],
49 link_type: LinkType,
50) -> Option<LaxPacketHeaders<'_>> {
51 match link_type {
52 LinkType::Ethernet(_) | LinkType::Unsupported(_) => {
53 LaxPacketHeaders::from_ethernet(packet).ok()
54 }
55 LinkType::RawIp(_) | LinkType::IPv4(_) | LinkType::IPv6(_) => {
56 LaxPacketHeaders::from_ip(packet).ok()
57 }
58 LinkType::LinuxSll(_) => from_linux_sll(packet, true),
59 LinkType::LinuxSll2(_) => from_linux_sll(packet, false),
60 LinkType::Null(_) | LinkType::Loop(_) => from_null(packet),
61 }
62}
63
64fn from_null(packet: &[u8]) -> Option<LaxPacketHeaders<'_>> {
65 if packet.len() <= 4 {
66 return None;
67 }
68
69 let is_valid_af_inet = {
70 fn matches(value: u32) -> bool {
72 match value {
73 2 | 24 | 28 | 30 => true,
76 _ => false,
77 }
78 }
79 let h = &packet[..4];
80 let b = [h[0], h[1], h[2], h[3]];
81 matches(u32::from_le_bytes(b)) || matches(u32::from_be_bytes(b))
84 };
85
86 if is_valid_af_inet {
87 LaxPacketHeaders::from_ip(&packet[4..]).ok()
88 } else {
89 None
90 }
91}
92
93fn from_linux_sll(packet: &[u8], is_v1: bool) -> Option<LaxPacketHeaders<'_>> {
95 let header_len = if is_v1 { 16 } else { 20 };
96 if packet.len() <= header_len {
97 return None;
98 }
99
100 let protocol_type = u16::from_be_bytes(if is_v1 {
101 [packet[14], packet[15]]
102 } else {
103 [packet[0], packet[1]]
104 });
105 let payload = &packet[header_len..];
106
107 Some(LaxPacketHeaders::from_ether_type(
108 EtherType(protocol_type),
109 payload,
110 ))
111}