1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/// TCP Option Kind
/// <https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-parameters-1>
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TcpOptionKind {
    Eol,
    Nop,
    Mss,
    Wscale,
    SackParmitted,
    Sack,
    Timestamp,
}

impl TcpOptionKind {
    /// Get the number of the TCP option kind
    pub fn number(&self) -> u8 {
        match *self {
            TcpOptionKind::Eol => 0,
            TcpOptionKind::Nop => 1,
            TcpOptionKind::Mss => 2,
            TcpOptionKind::Wscale => 3,
            TcpOptionKind::SackParmitted => 4,
            TcpOptionKind::Sack => 5,
            TcpOptionKind::Timestamp => 8,
        }
    }
    /// Get the name of the TCP option kind
    pub fn name(&self) -> String {
        match *self {
            TcpOptionKind::Eol => String::from("EOL"),
            TcpOptionKind::Nop => String::from("NOP"),
            TcpOptionKind::Mss => String::from("MSS"),
            TcpOptionKind::Wscale => String::from("WSCALE"),
            TcpOptionKind::SackParmitted => String::from("SACK_PERMITTED"),
            TcpOptionKind::Sack => String::from("SACK"),
            TcpOptionKind::Timestamp => String::from("TIMESTAMPS"),
        }
    }
}

/// TCP Flag Kind
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TcpFlagKind {
    Syn,
    Fin,
    Rst,
    Psh,
    Ack,
    Urg,
    Ece,
    Cwr,
}

impl TcpFlagKind {
    /// Get the number of the TCP flag kind
    pub fn number(&self) -> u8 {
        match *self {
            TcpFlagKind::Syn => pnet::packet::tcp::TcpFlags::SYN,
            TcpFlagKind::Fin => pnet::packet::tcp::TcpFlags::FIN,
            TcpFlagKind::Rst => pnet::packet::tcp::TcpFlags::RST,
            TcpFlagKind::Psh => pnet::packet::tcp::TcpFlags::PSH,
            TcpFlagKind::Ack => pnet::packet::tcp::TcpFlags::ACK,
            TcpFlagKind::Urg => pnet::packet::tcp::TcpFlags::URG,
            TcpFlagKind::Ece => pnet::packet::tcp::TcpFlags::ECE,
            TcpFlagKind::Cwr => pnet::packet::tcp::TcpFlags::CWR,
        }
    }
    /// Get the name of the TCP flag kind
    pub fn name(&self) -> String {
        match *self {
            TcpFlagKind::Syn => String::from("SYN"),
            TcpFlagKind::Fin => String::from("FIN"),
            TcpFlagKind::Rst => String::from("RST"),
            TcpFlagKind::Psh => String::from("PSH"),
            TcpFlagKind::Ack => String::from("ACK"),
            TcpFlagKind::Urg => String::from("URG"),
            TcpFlagKind::Ece => String::from("ECE"),
            TcpFlagKind::Cwr => String::from("CWR"),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct TcpFingerprint {
    pub source_port: u16,
    pub destination_port: u16,
    pub flags: Vec<TcpFlagKind>,
    pub window_size: u16,
    pub options: Vec<TcpOptionKind>,
    pub payload_length: u16,
    pub payload: Vec<u8>,
}