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}