1mod exported_pdu;
26mod pcap_nflog;
27
28pub use crate::data::exported_pdu::*;
29pub use crate::data::pcap_nflog::*;
30use crate::linktype::Linktype;
31use crate::read_u32_e;
32use nom::number::complete::be_u32;
33use nom::number::streaming::{be_u16, be_u64, be_u8};
34use nom::IResult;
35
36pub const ETHERTYPE_IPV4: u16 = 0x0800;
37pub const ETHERTYPE_IPV6: u16 = 0x86dd;
38
39#[derive(Clone, Debug)]
41pub enum PacketData<'a> {
42 L2(&'a [u8]),
43 L3(u16, &'a [u8]),
44 L4(u8, &'a [u8]),
45
46 Unsupported(&'a [u8]),
47}
48
49pub fn get_packetdata_null(i: &[u8], caplen: usize) -> Option<PacketData<'_>> {
61 if i.len() < caplen || caplen < 4 {
63 None
64 } else {
65 let vers = read_u32_e!(i, false);
66 let ethertype = match vers {
67 2 => ETHERTYPE_IPV4,
68 24 | 28 | 30 => ETHERTYPE_IPV6,
69 _ => 0,
70 };
71 Some(PacketData::L3(ethertype, &i[4..caplen]))
72 }
73}
74
75pub fn get_packetdata_ethernet(i: &[u8], caplen: usize) -> Option<PacketData<'_>> {
79 if i.len() < caplen || caplen == 0 {
80 None
81 } else {
82 Some(PacketData::L2(&i[..caplen]))
83 }
84}
85
86pub fn get_packetdata_raw(i: &[u8], caplen: usize) -> Option<PacketData<'_>> {
91 if i.len() < caplen || caplen == 0 {
92 None
93 } else {
94 let vers = i[0] >> 4;
95 let ethertype = match vers {
96 4 => ETHERTYPE_IPV4,
97 6 => ETHERTYPE_IPV6,
98 _ => 0,
99 };
100 Some(PacketData::L3(ethertype, &i[..caplen]))
101 }
102}
103
104pub fn get_packetdata_linux_sll(i: &[u8], caplen: usize) -> Option<PacketData<'_>> {
108 if i.len() < caplen || caplen == 0 {
109 None
110 } else {
111 match parse_sll_header(i) {
112 Err(_) => None,
113 Ok((rem, sll)) => {
114 match sll.arphrd_type {
115 778 => Some(PacketData::L4(47, rem)),
116 803 |
117 824 => None,
118 _ => Some(PacketData::L3(sll.proto, rem)),
119 }
120 }
121 }
122 }
123}
124
125struct SLLHeader {
126 _packet_type: u16,
127 arphrd_type: u16,
128 _ll_addr_len: u16,
129 _ll_addr: u64,
130 proto: u16,
131}
132
133fn parse_sll_header(i: &[u8]) -> IResult<&[u8], SLLHeader> {
134 let (i, _packet_type) = be_u16(i)?;
135 let (i, arphrd_type) = be_u16(i)?;
136 let (i, _ll_addr_len) = be_u16(i)?;
137 let (i, _ll_addr) = be_u64(i)?;
138 let (i, proto) = be_u16(i)?;
139 let header = SLLHeader {
140 _packet_type,
141 arphrd_type,
142 _ll_addr_len,
143 _ll_addr,
144 proto,
145 };
146 Ok((i, header))
147}
148
149pub fn get_packetdata_linux_sll2(i: &[u8], caplen: usize) -> Option<PacketData<'_>> {
153 if i.len() < caplen || caplen == 0 {
154 None
155 } else {
156 match parse_sll2_header(i) {
157 Err(_) => None,
158 Ok((rem, sll)) => {
159 match sll.arphrd_type {
160 778 => Some(PacketData::L4(47, rem)),
161 803 |
162 824 => None,
163 _ => Some(PacketData::L3(sll.protocol_type, rem)),
164 }
165 }
166 }
167 }
168}
169
170struct SLL2Header {
171 protocol_type: u16,
172 _reserved: u16,
173 _interface_index: u32,
174 arphrd_type: u16,
175 _packet_type: u8,
176 _ll_addr_len: u8,
177 _ll_addr: u64,
178}
179
180fn parse_sll2_header(i: &[u8]) -> IResult<&[u8], SLL2Header> {
181 let (i, protocol_type) = be_u16(i)?;
182 let (i, _reserved) = be_u16(i)?;
183 let (i, _interface_index) = be_u32(i)?;
184 let (i, arphrd_type) = be_u16(i)?;
185 let (i, _packet_type) = be_u8(i)?;
186 let (i, _ll_addr_len) = be_u8(i)?;
187 let (i, _ll_addr) = be_u64(i)?;
188 let header = SLL2Header {
189 protocol_type,
190 _reserved,
191 _interface_index,
192 arphrd_type,
193 _packet_type,
194 _ll_addr_len,
195 _ll_addr,
196 };
197 Ok((i, header))
198}
199
200pub fn get_packetdata_ipv4(i: &[u8], _caplen: usize) -> Option<PacketData<'_>> {
204 Some(PacketData::L3(ETHERTYPE_IPV4, i))
205}
206
207pub fn get_packetdata_ipv6(i: &[u8], _caplen: usize) -> Option<PacketData<'_>> {
211 Some(PacketData::L3(ETHERTYPE_IPV6, i))
212}
213
214pub fn get_packetdata(i: &[u8], linktype: Linktype, caplen: usize) -> Option<PacketData<'_>> {
219 match linktype {
220 Linktype::NULL => get_packetdata_null(i, caplen),
221 Linktype::ETHERNET => get_packetdata_ethernet(i, caplen),
222 Linktype::RAW => get_packetdata_raw(i, caplen),
223 Linktype::LINUX_SLL => get_packetdata_linux_sll(i, caplen),
224 Linktype::LINUX_SLL2 => get_packetdata_linux_sll2(i, caplen),
225 Linktype::IPV4 => get_packetdata_ipv4(i, caplen),
226 Linktype::IPV6 => get_packetdata_ipv6(i, caplen),
227 Linktype::NFLOG => get_packetdata_nflog(i, caplen),
228 Linktype::WIRESHARK_UPPER_PDU => get_packetdata_wireshark_upper_pdu(i, caplen),
229 _ => Some(PacketData::Unsupported(i)),
230 }
231}