net_file/translator/
global_header.rs

1use std::fmt;
2
3use serde_derive::Serialize;
4
5/// https://tshark.dev/formats/pcap_deconstruction/
6// typedef struct pcap_hdr_s {
7//     guint32 magic_number;   /* magic number */
8//     guint16 version_major;  /* major version number */
9//     guint16 version_minor;  /* minor version number */
10//     gint32  thiszone;       /* GMT to local correction */
11//     guint32 sigfigs;        /* accuracy of timestamps */
12//     guint32 snaplen;        /* max length of captured packets, in octets */
13//     guint32 network;        /* data link type */
14// } pcap_hdr_t;
15//
16// Header size = 24 bytes:
17///
18/// ```
19#[derive(Serialize)]
20pub struct GlobalHeader {
21    // magic_number = 4 bytes (d4 c3 b2 a1)
22    // Magic Number Types https://tshark.dev/formats/pcap_deconstruction/
23    magic_number: u32,
24    // version_major = 2 bytes (02 00)
25    version_major: u16,
26    // version_minor = 2 bytes (04 00) *in our case 2.4. (little endian)
27    version_minor: u16,
28    // thiszone = 4 bytes (00 00 00 00) *usually set to 0
29    thiszone: u32,
30    // sigfigs = 4 bytes (00 00 00 00) *usually set to 0
31    sigfigs: u32,
32    // snaplen = 4 bytes (FF FF 00 00) *maximum length of the captured packets (data#) in bytes, here its 65535 (0xffff) which is default value for tcpdump and wireshark)
33    snaplen: u32,
34    // network = 4 bytes (01 00 00 00) *0x1 which indicates that the link-layer protocol is Ethernet.
35    // Full list: http://www.tcpdump.org/linktypes.html
36    network: u32,
37}
38
39const PCAPH_MAGIC_NUM_LE: u32 = 3569595041;
40const PCAPH_VER_MAJOR: u16 = 2;
41const PCAPH_VER_MINOR: u16 = 4;
42const PCAPH_THISZONE: u32 = 0;
43const PCAPH_SIGFIGS: u32 = 0;
44const PCAPH_SNAPLEN: u32 = 65535;
45const LINKTYPE_ETHERNET: u32 = 1;
46
47impl Default for GlobalHeader {
48    fn default() -> Self {
49        let pcaph_magic_num_be = u32::from_be(PCAPH_MAGIC_NUM_LE);
50
51        GlobalHeader {
52            magic_number: pcaph_magic_num_be,
53            version_major: PCAPH_VER_MAJOR,
54            version_minor: PCAPH_VER_MINOR,
55            thiszone: PCAPH_THISZONE,
56            sigfigs: PCAPH_SIGFIGS,
57            snaplen: PCAPH_SNAPLEN,
58            network: LINKTYPE_ETHERNET,
59        }
60    }
61}
62
63impl fmt::Debug for GlobalHeader {
64    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65        write!(f, "GlobalHeader {{ magic_number={}, version_major={}, version_minor={}, thiszone={}, sigfigs={}, snaplen={}, network={}, binary={:?} }}",
66               self.magic_number,
67               self.version_major,
68               self.version_minor,
69               self.thiszone,
70               self.sigfigs,
71               self.snaplen,
72               self.network,
73               self.to_bytes())
74    }
75}
76
77impl GlobalHeader {
78    pub fn to_bytes(&self) -> Vec<u8> {
79        bincode::serialize(&self).unwrap()
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    const PCAPH_MAGIC_NUM_BE: u32 = 2712847316;
88
89    #[test]
90    fn expected_create_global_header() {
91        let global_header = GlobalHeader::default();
92        let buf = global_header.to_bytes();
93
94        println!("{:?}", global_header);
95        assert_eq!(24, buf.len());
96        assert_eq!(PCAPH_MAGIC_NUM_BE, global_header.magic_number);
97        assert_eq!(PCAPH_VER_MAJOR, global_header.version_major);
98        assert_eq!(PCAPH_VER_MINOR, global_header.version_minor);
99        assert_eq!(PCAPH_THISZONE, global_header.thiszone);
100        assert_eq!(PCAPH_SIGFIGS, global_header.sigfigs);
101        assert_eq!(PCAPH_SNAPLEN, global_header.snaplen);
102        assert_eq!(LINKTYPE_ETHERNET, global_header.network);
103    }
104}