1#[cfg(feature = "pcap")]
2use bincode::Decode;
3#[cfg(feature = "pcap")]
4use bincode::Encode;
5#[cfg(feature = "pcap")]
6use byteorder::BigEndian;
7#[cfg(feature = "pcap")]
8use byteorder::LittleEndian;
9#[cfg(feature = "pcap")]
10use byteorder::ReadBytesExt;
11#[cfg(feature = "pcap")]
12use byteorder::WriteBytesExt;
13#[cfg(feature = "pcap")]
14use serde::Deserialize;
15#[cfg(feature = "pcap")]
16use serde::Serialize;
17#[cfg(feature = "pcap")]
18use std::fs::File;
19#[cfg(feature = "pcap")]
20use std::io::Read;
21#[cfg(feature = "pcap")]
22use std::io::Write;
23#[cfg(feature = "pcap")]
24use std::time::SystemTime;
25#[cfg(feature = "pcap")]
26use std::time::UNIX_EPOCH;
27#[cfg(feature = "pcap")]
28use strum::IntoEnumIterator;
29#[cfg(feature = "pcap")]
30use strum_macros::EnumIter;
31#[cfg(feature = "pcap")]
32use strum_macros::EnumString;
33
34#[cfg(feature = "pcap")]
35use crate::PcapByteOrder;
36#[cfg(feature = "pcap")]
37use crate::error::PcaptureError;
38
39#[cfg(feature = "pcap")]
40#[repr(u32)]
41#[derive(Debug, Clone, Copy, EnumString, EnumIter, Serialize, Deserialize, Encode, Decode)]
42pub enum LinkType {
43 NULL = 0,
44 ETHERNET = 1,
45 AX25 = 3,
46 IEEE8025 = 6,
47 ARCNETBSD = 7,
48 SLIP = 8,
49 PPP = 9,
50 FDDI = 10,
51 PPPHDLC = 50,
52 PPPETHER = 51,
53 ATMRFC1483 = 100,
54 RAW = 101,
55 CHDLC = 104,
56 IEEE80211 = 105,
57 FRELAY = 107,
58 LOOP = 108,
59 LINUXSLL = 113,
60 LTALK = 114,
61 PFLOG = 117,
62 IEEE80211PRISM = 119,
63 IPOVERFC = 122,
64 SUNATM = 123,
65 IEEE80211RADIOTAP = 127,
66 ARCNETLINUX = 129,
67 APPLEIPOVERIEEE1394 = 138,
68 MTP2WITHPHDR = 139,
69 MTP2 = 140,
70 MTP3 = 141,
71 SCCP = 142,
72 DOCSIS = 143,
73 LINUXIRDA = 144,
74 IEEE80211AVS = 163,
75 BACNETMSTP = 165,
76 PPPPPPD = 166,
77 GPRSLLC = 169,
78 GPFT = 170,
79 GPFF = 171,
80 LINUXLAPD = 177,
81 MFR = 182,
82 BLUETOOTHHCIH4 = 187,
83 USBLINUX = 189,
84 PPI = 192,
85 IEEE802154WITHFCS = 195,
86 SITA = 196,
87 ERF = 197,
88 BLUETOOTHHCIH4WITHPHDR = 201,
89 AX25KISS = 202,
90 LAPD = 203,
91 PPPWITHDIR = 204,
92 CHDLCWITHDIR = 205,
93 FRELAYWITHDIR = 206,
94 LAPBWITHDIR = 207,
95 IPMBLINUX = 209,
96 IEEE802154NONASKPHY = 215,
97 USBLINUXMMAPPED = 220,
98 FC2 = 224,
99 FC2WITHFRAMEDELIMS = 225,
100 IPNET = 226,
101 CANSOCKETCAN = 227,
102 IPV4 = 228,
103 IPV6 = 229,
104 IEEE802154NOFCS = 230,
105 DBUS = 231,
106 DVBCI = 235,
107 MUX27010 = 236,
108 STANAG5066DPDU = 237,
109 NFLOG = 239,
110 NETANALYZER = 240,
111 NETANALYZERTRANSPARENT = 241,
112 IPOIB = 242,
113 MPEG2TS = 243,
114 NG40 = 244,
115 NFCLLCP = 245,
116 INFINIBAND = 247,
117 SCTP = 248,
118 USBPCAP = 249,
119 RTACSERIAL = 250,
120 BLUETOOTHLELL = 251,
121 WIRESHARKUPPERPDU = 252,
122 NETLINK = 253,
123 BLUETOOTHLINUXMONITOR = 254,
124 BLUETOOTHBREDRBB = 255,
125 BLUETOOTHLELLWITHPHDR = 256,
126 PROFIBUSDL = 257,
127 PKTAP = 258,
128 EPON = 259,
129 IPMIHPM2 = 260,
130 ZWAVER1R2 = 261,
131 ZWAVER3 = 262,
132 WATTSTOPPERDLM = 263,
133 ISO14443 = 264,
134 RDS = 265,
135 USBDARWIN = 266,
136 SDLC = 268,
137 LORATAP = 270,
138 VSOCK = 271,
139 NORDICBLE = 272,
140 DOCSIS31XRA31 = 273,
141 ETHERNETMPACKET = 274,
142 DISPLAYPORTAUX = 275,
143 LINUXSLL2 = 276,
144 OPENVIZSLA = 278,
145 EBHSCR = 279,
146 VPPDISPATCH = 280,
147 DSATAGBRCM = 281,
148 DSATAGBRCMPREPEND = 282,
149 IEEE802154TAP = 283,
150 DSATAGDSA = 284,
151 DSATAGEDSA = 285,
152 ELEE = 286,
153 WAVESERIAL = 287,
154 USB20 = 288,
155 ATSCALP = 289,
156}
157
158#[cfg(feature = "pcap")]
159impl LinkType {
160 pub fn to_u32(self) -> u32 {
161 self as u32
162 }
163 pub fn from_u32(value: u32) -> Option<Self> {
164 LinkType::iter().find(|&e| e.to_u32() == value)
165 }
166}
167
168#[cfg(feature = "pcap")]
188#[repr(C)]
189#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)]
190pub struct FileHeader {
191 pub magic_number: u32,
196 pub major_version: u16,
200 pub minor_version: u16,
204 reserved1: u32,
207 reserved2: u32,
210 pub snaplen: u32,
214 pub linktype: LinkType,
219}
220
221#[cfg(feature = "pcap")]
222impl Default for FileHeader {
223 fn default() -> Self {
224 FileHeader {
225 magic_number: 0xa1b2c3d4,
227 major_version: 2,
228 minor_version: 4,
229 reserved1: 0,
230 reserved2: 0,
231 snaplen: 0,
233 linktype: LinkType::ETHERNET,
234 }
235 }
236}
237
238#[cfg(feature = "pcap")]
239impl FileHeader {
240 pub fn write(&self, fs: &mut File, pbo: PcapByteOrder) -> Result<(), PcaptureError> {
241 match pbo {
242 PcapByteOrder::LittleEndian | PcapByteOrder::WiresharkDefault => {
243 fs.write_u32::<LittleEndian>(self.magic_number)?;
244 fs.write_u16::<LittleEndian>(self.major_version)?;
245 fs.write_u16::<LittleEndian>(self.minor_version)?;
246 fs.write_u32::<LittleEndian>(self.reserved1)?;
247 fs.write_u32::<LittleEndian>(self.reserved2)?;
248 fs.write_u32::<LittleEndian>(self.snaplen)?;
249 fs.write_u32::<LittleEndian>(self.linktype.to_u32())?;
250 }
251 PcapByteOrder::BigEndian => {
252 fs.write_u32::<BigEndian>(self.magic_number)?;
253 fs.write_u16::<BigEndian>(self.major_version)?;
254 fs.write_u16::<BigEndian>(self.minor_version)?;
255 fs.write_u32::<BigEndian>(self.reserved1)?;
256 fs.write_u32::<BigEndian>(self.reserved2)?;
257 fs.write_u32::<BigEndian>(self.snaplen)?;
258 fs.write_u32::<BigEndian>(self.linktype.to_u32())?;
259 }
260 }
261 Ok(())
262 }
263 pub fn read(fs: &mut File, pbo: PcapByteOrder) -> Result<FileHeader, PcaptureError> {
264 match pbo {
265 PcapByteOrder::LittleEndian | PcapByteOrder::WiresharkDefault => {
266 let magic_number = fs.read_u32::<LittleEndian>()?;
267 let major_version = fs.read_u16::<LittleEndian>()?;
268 let minor_version = fs.read_u16::<LittleEndian>()?;
269 let reserved1 = fs.read_u32::<LittleEndian>()?;
270 let reserved2 = fs.read_u32::<LittleEndian>()?;
271 let snaplen = fs.read_u32::<LittleEndian>()?;
272 let linktype_value = fs.read_u32::<LittleEndian>()?;
273 let linktype = match LinkType::from_u32(linktype_value) {
274 Some(l) => l,
275 None => {
276 return Err(PcaptureError::UnknownLinkType {
277 linktype: linktype_value,
278 });
279 }
280 };
281 Ok(FileHeader {
282 magic_number,
283 major_version,
284 minor_version,
285 reserved1,
286 reserved2,
287 snaplen,
288 linktype,
289 })
290 }
291 PcapByteOrder::BigEndian => {
292 let magic_number = fs.read_u32::<BigEndian>()?;
293 let major_version = fs.read_u16::<BigEndian>()?;
294 let minor_version = fs.read_u16::<BigEndian>()?;
295 let reserved1 = fs.read_u32::<BigEndian>()?;
296 let reserved2 = fs.read_u32::<BigEndian>()?;
297 let snaplen = fs.read_u32::<BigEndian>()?;
298 let linktype_value = fs.read_u32::<BigEndian>()?;
299 let linktype = match LinkType::from_u32(linktype_value) {
300 Some(l) => l,
301 None => {
302 return Err(PcaptureError::UnknownLinkType {
303 linktype: linktype_value,
304 });
305 }
306 };
307 Ok(FileHeader {
308 magic_number,
309 major_version,
310 minor_version,
311 reserved1,
312 reserved2,
313 snaplen,
314 linktype,
315 })
316 }
317 }
318 }
319}
320
321#[cfg(feature = "pcap")]
341#[repr(C)]
342#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)]
343pub struct PacketRecord {
344 pub ts_sec: u32,
347 pub ts_usec: u32,
348 pub captured_packet_length: u32,
352 pub original_packet_length: u32,
356 pub packet_data: Vec<u8>,
360}
361
362#[cfg(feature = "pcap")]
363impl PacketRecord {
364 pub fn new(packet_data: &[u8], snaplen: usize) -> Result<PacketRecord, PcaptureError> {
365 let packet_slice = if packet_data.len() > snaplen {
366 &packet_data[..snaplen]
367 } else {
368 packet_data
369 };
370 let dura = SystemTime::now().duration_since(UNIX_EPOCH)?;
371 let ts_sec = dura.as_secs() as u32;
381 let ts_usec = dura.subsec_micros();
382 let captured_packet_length = packet_slice.len() as u32;
383 let original_packet_length = packet_data.len() as u32;
384 Ok(PacketRecord {
385 ts_sec,
386 ts_usec,
387 captured_packet_length,
388 original_packet_length,
389 packet_data: packet_data.to_vec(),
390 })
391 }
392 pub fn write(&self, fs: &mut File, pbo: PcapByteOrder) -> Result<(), PcaptureError> {
393 match pbo {
394 PcapByteOrder::LittleEndian | PcapByteOrder::WiresharkDefault => {
395 fs.write_u32::<LittleEndian>(self.ts_sec)?;
396 fs.write_u32::<LittleEndian>(self.ts_usec)?;
397 fs.write_u32::<LittleEndian>(self.captured_packet_length)?;
398 fs.write_u32::<LittleEndian>(self.original_packet_length)?;
399 fs.write_all(&self.packet_data)?;
400 }
401 PcapByteOrder::BigEndian => {
402 fs.write_u32::<BigEndian>(self.ts_sec)?;
403 fs.write_u32::<BigEndian>(self.ts_usec)?;
404 fs.write_u32::<BigEndian>(self.captured_packet_length)?;
405 fs.write_u32::<BigEndian>(self.original_packet_length)?;
406 fs.write_all(&self.packet_data)?;
407 }
408 }
409 Ok(())
410 }
411 pub fn read(fs: &mut File, pbo: PcapByteOrder) -> Result<PacketRecord, PcaptureError> {
412 let (ts_sec, ts_usec, captured_packet_length, original_packet_length) = match pbo {
413 PcapByteOrder::LittleEndian | PcapByteOrder::WiresharkDefault => {
414 let ts_sec = fs.read_u32::<LittleEndian>()?;
415 let ts_usec = fs.read_u32::<LittleEndian>()?;
416 let captured_packet_length = fs.read_u32::<LittleEndian>()?;
417 let original_packet_length = fs.read_u32::<LittleEndian>()?;
418 (
419 ts_sec,
420 ts_usec,
421 captured_packet_length,
422 original_packet_length,
423 )
424 }
425 PcapByteOrder::BigEndian => {
426 let ts_sec = fs.read_u32::<BigEndian>()?;
427 let ts_usec = fs.read_u32::<BigEndian>()?;
428 let captured_packet_length = fs.read_u32::<BigEndian>()?;
429 let original_packet_length = fs.read_u32::<BigEndian>()?;
430 (
431 ts_sec,
432 ts_usec,
433 captured_packet_length,
434 original_packet_length,
435 )
436 }
437 };
438 let mut data = vec![0u8; captured_packet_length as usize]; fs.read_exact(&mut data)?;
440 Ok(PacketRecord {
441 ts_sec,
442 ts_usec,
443 captured_packet_length,
444 original_packet_length,
445 packet_data: data,
446 })
447 }
448}
449
450#[cfg(feature = "pcap")]
451#[repr(C)]
452#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)]
453pub struct Pcap {
454 pub pbo: PcapByteOrder,
455 pub header: FileHeader,
456 pub records: Vec<PacketRecord>,
457}
458
459#[cfg(feature = "pcap")]
460impl Pcap {
461 pub fn new(pbo: PcapByteOrder) -> Pcap {
462 Pcap {
463 pbo,
464 header: FileHeader::default(),
465 records: Vec::new(),
466 }
467 }
468 pub fn append(&mut self, record: PacketRecord) {
469 if record.packet_data.len() as u32 > self.header.snaplen {
470 self.header.snaplen = record.packet_data.len() as u32;
471 }
472 self.records.push(record);
473 }
474 pub fn write(&self, fs: &mut File) -> Result<(), PcaptureError> {
475 self.header.write(fs, self.pbo)?;
476 for r in &self.records {
477 r.write(fs, self.pbo)?;
478 }
479 Ok(())
480 }
481 pub fn write_all(&self, path: &str) -> Result<(), PcaptureError> {
482 let mut fs = File::create(path)?;
483 Self::write(self, &mut fs)?;
484 Ok(())
485 }
486 pub fn read_all(path: &str, pbo: PcapByteOrder) -> Result<Pcap, PcaptureError> {
487 let mut fs = File::open(path)?;
488 let header = FileHeader::read(&mut fs, pbo)?;
489 let mut record = Vec::new();
490 loop {
491 match PacketRecord::read(&mut fs, pbo) {
492 Ok(r) => record.push(r),
493 Err(e) => match e {
494 PcaptureError::IOError(_) => break, _ => return Err(e),
496 },
497 }
498 }
499 Ok(Pcap {
500 pbo,
501 header,
502 records: record,
503 })
504 }
505}