cross_socket/packet/
tcp.rs

1use pnet::packet::Packet;
2use std::net::{IpAddr, SocketAddr};
3use crate::packet::ethernet::ETHERNET_HEADER_LEN;
4use crate::packet::ipv4::IPV4_HEADER_LEN;
5use crate::packet::ipv6::IPV6_HEADER_LEN;
6
7/// Minimum TCP Header Length
8pub const TCP_HEADER_LEN: usize = pnet::packet::tcp::MutableTcpPacket::minimum_packet_size();
9/// Minimum TCP Data Offset
10pub const TCP_MIN_DATA_OFFSET: u8 = 5;
11/// Maximum TCP Option Length
12pub const TCP_OPTION_MAX_LEN: usize = 40;
13/// Maximum TCP Header Length (with options)
14pub const TCP_HEADER_MAX_LEN: usize = TCP_HEADER_LEN + TCP_OPTION_MAX_LEN;
15/// Default TCP Option Length
16pub const TCP_DEFAULT_OPTION_LEN: usize = 12;
17/// Default TCP Source Port
18pub const DEFAULT_SRC_PORT: u16 = 53443;
19
20/// TCP (IPv4) Minimum Packet Length
21pub const TCPV4_MINIMUM_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV4_HEADER_LEN + TCP_HEADER_LEN;
22/// TCP (IPv4) Default Packet Length
23pub const TCPV4_DEFAULT_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV4_HEADER_LEN + TCP_HEADER_LEN + TCP_DEFAULT_OPTION_LEN;
24/// TCP (IPv4) Minimum IP Packet Length
25pub const TCPV4_MINIMUM_IP_PACKET_LEN: usize = IPV4_HEADER_LEN + TCP_HEADER_LEN;
26/// TCP (IPv4) Default IP Packet Length
27pub const TCPV4_DEFAULT_IP_PACKET_LEN: usize = IPV4_HEADER_LEN + TCP_HEADER_LEN + TCP_DEFAULT_OPTION_LEN;
28/// TCP (IPv6) Minimum Packet Length
29pub const TCPV6_MINIMUM_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + TCP_HEADER_LEN;
30/// TCP (IPv6) Default Packet Length
31pub const TCPV6_DEFAULT_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + TCP_HEADER_LEN + TCP_DEFAULT_OPTION_LEN;
32/// TCP (IPv6) Minimum IP Packet Length
33pub const TCPV6_MINIMUM_IP_PACKET_LEN: usize = IPV6_HEADER_LEN + TCP_HEADER_LEN;
34/// TCP (IPv6) Default IP Packet Length
35pub const TCPV6_DEFAULT_IP_PACKET_LEN: usize = IPV6_HEADER_LEN + TCP_HEADER_LEN + TCP_DEFAULT_OPTION_LEN;
36
37/// TCP Option Kind
38/// <https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-parameters-1>
39#[derive(Clone, Copy, Debug, PartialEq)]
40pub enum TcpOptionKind {
41    Eol,
42    Nop,
43    Mss,
44    Wscale,
45    SackParmitted,
46    Sack,
47    Timestamp,
48}
49
50impl TcpOptionKind {
51    pub fn from_u8(n: u8) -> TcpOptionKind {
52        match n {
53            0 => TcpOptionKind::Eol,
54            1 => TcpOptionKind::Nop,
55            2 => TcpOptionKind::Mss,
56            3 => TcpOptionKind::Wscale,
57            4 => TcpOptionKind::SackParmitted,
58            5 => TcpOptionKind::Sack,
59            8 => TcpOptionKind::Timestamp,
60            _ => panic!("Unknown TCP option kind: {}", n),
61        }
62    }
63    /// Get the number of the TCP option kind
64    pub fn number(&self) -> u8 {
65        match *self {
66            TcpOptionKind::Eol => 0,
67            TcpOptionKind::Nop => 1,
68            TcpOptionKind::Mss => 2,
69            TcpOptionKind::Wscale => 3,
70            TcpOptionKind::SackParmitted => 4,
71            TcpOptionKind::Sack => 5,
72            TcpOptionKind::Timestamp => 8,
73        }
74    }
75    /// Get the ID of the TCP option kind
76    pub fn id(&self) -> String {
77        match *self {
78            TcpOptionKind::Eol => String::from("EOL"),
79            TcpOptionKind::Nop => String::from("NOP"),
80            TcpOptionKind::Mss => String::from("MSS"),
81            TcpOptionKind::Wscale => String::from("WSCALE"),
82            TcpOptionKind::SackParmitted => String::from("SACK_PERMITTED"),
83            TcpOptionKind::Sack => String::from("SACK"),
84            TcpOptionKind::Timestamp => String::from("TIMESTAMPS"),
85        }
86    }
87    /// Get the name of the TCP option kind
88    pub fn name(&self) -> String {
89        match *self {
90            TcpOptionKind::Eol => String::from("EOL"),
91            TcpOptionKind::Nop => String::from("NOP"),
92            TcpOptionKind::Mss => String::from("MSS"),
93            TcpOptionKind::Wscale => String::from("WSCALE"),
94            TcpOptionKind::SackParmitted => String::from("SACK_PERMITTED"),
95            TcpOptionKind::Sack => String::from("SACK"),
96            TcpOptionKind::Timestamp => String::from("TIMESTAMPS"),
97        }
98    }
99    /// Get size (bytes) of the TCP option
100    pub fn size(&self) -> usize {
101        match *self {
102            TcpOptionKind::Eol => 1,
103            TcpOptionKind::Nop => 1,
104            TcpOptionKind::Mss => 4,
105            TcpOptionKind::Wscale => 3,
106            TcpOptionKind::SackParmitted => 2,
107            TcpOptionKind::Sack => 10,
108            TcpOptionKind::Timestamp => 10,
109        }
110    }
111}
112
113/// TCP Option
114#[derive(Clone, Debug, PartialEq)]
115pub struct TcpOption {
116    /// TCP Option Kind
117    pub kind: TcpOptionKind,
118    /// TCP Option Data
119    pub data: Vec<u8>,
120}
121
122impl TcpOption {
123    /// No Operation (NOP) TCP option.
124    pub fn nop() -> Self {
125        TcpOption {
126            kind: TcpOptionKind::Nop,
127            data: vec![],
128        }
129    }
130    /// Timestamp TCP option
131    pub fn timestamp(my: u32, their: u32) -> Self {
132        let mut data = vec![];
133        data.extend_from_slice(&my.to_be_bytes());
134        data.extend_from_slice(&their.to_be_bytes());
135
136        TcpOption {
137            kind: TcpOptionKind::Timestamp,
138            data: data,
139        }
140    }
141    /// Get the timestamp of the TCP option
142    pub fn get_timestamp(&self) -> (u32, u32) {
143        let mut my: [u8; 4] = [0; 4];
144        my.copy_from_slice(&self.data[0..4]);
145        let mut their: [u8; 4] = [0; 4];
146        their.copy_from_slice(&self.data[4..8]);
147        (u32::from_be_bytes(my), u32::from_be_bytes(their))
148    }
149    /// Maximum Segment Size (MSS) TCP option
150    pub fn mss(val: u16) -> Self {
151        let mut data = vec![];
152        data.extend_from_slice(&val.to_be_bytes());
153
154        TcpOption {
155            kind: TcpOptionKind::Mss,
156            data: data,
157        }
158    }
159    /// Get the MSS of the TCP option
160    pub fn get_mss(&self) -> u16 {
161        let mut mss: [u8; 2] = [0; 2];
162        mss.copy_from_slice(&self.data[0..2]);
163        u16::from_be_bytes(mss)
164    }
165    /// Window Scale (WSCALE) TCP option
166    pub fn wscale(val: u8) -> Self {
167        TcpOption {
168            kind: TcpOptionKind::Wscale,
169            data: vec![val],
170        }
171    }
172    /// Get the WSCALE of the TCP option
173    pub fn get_wscale(&self) -> u8 {
174        self.data[0]
175    }
176    /// Selective Acknowledgement Permitted (SACK_PERMITTED) TCP option
177    pub fn sack_perm() -> Self {
178        TcpOption {
179            kind: TcpOptionKind::SackParmitted,
180            data: vec![],
181        }
182    }
183    /// Selective Acknowledgement (SACK) TCP option
184    pub fn selective_ack(acks: &[u32]) -> Self {
185        let mut data = vec![];
186        for ack in acks {
187            data.extend_from_slice(&ack.to_be_bytes());
188        }
189        TcpOption {
190            kind: TcpOptionKind::Sack,
191            data: data,
192        }
193    }
194
195    pub(crate) fn from_pnet_type(opt: pnet::packet::tcp::TcpOptionPacket) -> TcpOption {
196        TcpOption {
197            kind: TcpOptionKind::from_u8(opt.get_number().0),
198            data: opt.payload().to_vec(),
199        }
200    }
201
202    pub(crate) fn to_pnet_type(&self) -> pnet::packet::tcp::TcpOption {
203        match self.kind {
204            TcpOptionKind::Nop => pnet::packet::tcp::TcpOption::nop(),
205            TcpOptionKind::Mss => pnet::packet::tcp::TcpOption::mss(self.get_mss()),
206            TcpOptionKind::Wscale => pnet::packet::tcp::TcpOption::wscale(self.get_wscale()),
207            TcpOptionKind::SackParmitted => pnet::packet::tcp::TcpOption::sack_perm(),
208            TcpOptionKind::Sack => {
209                let mut acks: Vec<u32> = vec![];
210                for i in 0..self.data.len() / 4 {
211                    let mut ack: [u8; 4] = [0; 4];
212                    ack.copy_from_slice(&self.data[i * 4..i * 4 + 4]);
213                    acks.push(u32::from_be_bytes(ack));
214                }
215                pnet::packet::tcp::TcpOption::selective_ack(&acks)
216            }
217            TcpOptionKind::Timestamp => {
218                let (my, their) = self.get_timestamp();
219                pnet::packet::tcp::TcpOption::timestamp(my, their)
220            }
221            _ => pnet::packet::tcp::TcpOption::nop(),
222        }
223    }
224}
225
226/// TCP Flag Kind
227#[derive(Clone, Copy, Debug, PartialEq)]
228pub enum TcpFlag {
229    Syn,
230    Fin,
231    Rst,
232    Psh,
233    Ack,
234    Urg,
235    Ece,
236    Cwr,
237    Unknown(u8),
238}
239
240impl TcpFlag {
241    /// Get the TCP flag kind from u8
242    pub fn from_u8(n: u8) -> TcpFlag {
243        match n {
244            pnet::packet::tcp::TcpFlags::SYN => TcpFlag::Syn,
245            pnet::packet::tcp::TcpFlags::FIN => TcpFlag::Fin,
246            pnet::packet::tcp::TcpFlags::RST => TcpFlag::Rst,
247            pnet::packet::tcp::TcpFlags::PSH => TcpFlag::Psh,
248            pnet::packet::tcp::TcpFlags::ACK => TcpFlag::Ack,
249            pnet::packet::tcp::TcpFlags::URG => TcpFlag::Urg,
250            pnet::packet::tcp::TcpFlags::ECE => TcpFlag::Ece,
251            pnet::packet::tcp::TcpFlags::CWR => TcpFlag::Cwr,
252            _ => TcpFlag::Unknown(n),
253        }
254    }
255    /// Get the number of the TCP flag kind
256    pub fn number(&self) -> u8 {
257        match *self {
258            TcpFlag::Syn => pnet::packet::tcp::TcpFlags::SYN,
259            TcpFlag::Fin => pnet::packet::tcp::TcpFlags::FIN,
260            TcpFlag::Rst => pnet::packet::tcp::TcpFlags::RST,
261            TcpFlag::Psh => pnet::packet::tcp::TcpFlags::PSH,
262            TcpFlag::Ack => pnet::packet::tcp::TcpFlags::ACK,
263            TcpFlag::Urg => pnet::packet::tcp::TcpFlags::URG,
264            TcpFlag::Ece => pnet::packet::tcp::TcpFlags::ECE,
265            TcpFlag::Cwr => pnet::packet::tcp::TcpFlags::CWR,
266            TcpFlag::Unknown(n) => n,
267        }
268    }
269    /// Get the ID of the TCP flag kind
270    pub fn id(&self) -> String {
271        match *self {
272            TcpFlag::Syn => String::from("SYN"),
273            TcpFlag::Fin => String::from("FIN"),
274            TcpFlag::Rst => String::from("RST"),
275            TcpFlag::Psh => String::from("PSH"),
276            TcpFlag::Ack => String::from("ACK"),
277            TcpFlag::Urg => String::from("URG"),
278            TcpFlag::Ece => String::from("ECE"),
279            TcpFlag::Cwr => String::from("CWR"),
280            TcpFlag::Unknown(n) => format!("UNKNOWN_{}", n),
281        }
282    }
283    /// Get the name of the TCP flag kind
284    pub fn name(&self) -> String {
285        match *self {
286            TcpFlag::Syn => String::from("SYN"),
287            TcpFlag::Fin => String::from("FIN"),
288            TcpFlag::Rst => String::from("RST"),
289            TcpFlag::Psh => String::from("PSH"),
290            TcpFlag::Ack => String::from("ACK"),
291            TcpFlag::Urg => String::from("URG"),
292            TcpFlag::Ece => String::from("ECE"),
293            TcpFlag::Cwr => String::from("CWR"),
294            TcpFlag::Unknown(n) => format!("Unknown({})", n),
295        }
296    }
297}
298
299/// Get the length of TCP options from TCP data offset
300pub fn get_tcp_options_length(data_offset: u8) -> usize {
301    if data_offset > 5 {
302        data_offset as usize * 4 - TCP_HEADER_LEN
303    } else {
304        0
305    }
306}
307
308/// Get the TCP data offset from TCP options
309pub fn get_tcp_data_offset(opstions: Vec<TcpOption>) -> u8 {
310    let mut total_size: u8 = 0;
311    for opt in opstions {
312        total_size += opt.kind.size() as u8;
313    }
314    if total_size % 4 == 0 {
315        total_size / 4 + TCP_MIN_DATA_OFFSET
316    } else {
317        total_size / 4 + TCP_MIN_DATA_OFFSET + 1
318    }
319}
320
321/// Represents a TCP packet.
322#[derive(Clone, Debug, PartialEq)]
323pub struct TcpPacket {
324    /// Source port
325    pub source: u16,
326    /// Destination port
327    pub destination: u16,
328    /// Sequence number
329    pub sequence: u32,
330    /// Acknowledgement number
331    pub acknowledgement: u32,
332    /// Data offset
333    pub data_offset: u8,
334    /// Reserved
335    pub reserved: u8,
336    /// TCP flags
337    pub flags: Vec<TcpFlag>,
338    /// Window size
339    pub window: u16,
340    /// Checksum
341    pub checksum: u16,
342    /// Urgent pointer
343    pub urgent_ptr: u16,
344    /// TCP options
345    pub options: Vec<TcpOption>,
346    /// TCP Payload
347    pub payload: Vec<u8>,
348}
349
350impl TcpPacket {
351    pub(crate) fn from_pnet_packet(packet: &pnet::packet::tcp::TcpPacket) -> TcpPacket {
352        let mut tcp_options: Vec<TcpOption> = vec![];
353        for opt in packet.get_options_iter() {
354            tcp_options.push(TcpOption::from_pnet_type(opt));
355        }
356        let mut tcp_flags: Vec<TcpFlag> = vec![];
357        if packet.get_flags() & TcpFlag::Syn.number() == TcpFlag::Syn.number() {
358            tcp_flags.push(TcpFlag::Syn);
359        }
360        if packet.get_flags() & TcpFlag::Fin.number() == TcpFlag::Fin.number() {
361            tcp_flags.push(TcpFlag::Fin);
362        }
363        if packet.get_flags() & TcpFlag::Rst.number() == TcpFlag::Rst.number() {
364            tcp_flags.push(TcpFlag::Rst);
365        }
366        if packet.get_flags() & TcpFlag::Psh.number() == TcpFlag::Psh.number() {
367            tcp_flags.push(TcpFlag::Psh);
368        }
369        if packet.get_flags() & TcpFlag::Ack.number() == TcpFlag::Ack.number() {
370            tcp_flags.push(TcpFlag::Ack);
371        }
372        if packet.get_flags() & TcpFlag::Urg.number() == TcpFlag::Urg.number() {
373            tcp_flags.push(TcpFlag::Urg);
374        }
375        if packet.get_flags() & TcpFlag::Ece.number() == TcpFlag::Ece.number() {
376            tcp_flags.push(TcpFlag::Ece);
377        }
378        if packet.get_flags() & TcpFlag::Cwr.number() == TcpFlag::Cwr.number() {
379            tcp_flags.push(TcpFlag::Cwr);
380        }
381        TcpPacket {
382            source: packet.get_source(),
383            destination: packet.get_destination(),
384            sequence: packet.get_sequence(),
385            acknowledgement: packet.get_acknowledgement(),
386            data_offset: packet.get_data_offset(),
387            reserved: packet.get_reserved(),
388            flags: tcp_flags,
389            window: packet.get_window(),
390            checksum: packet.get_checksum(),
391            urgent_ptr: packet.get_urgent_ptr(),
392            options: tcp_options,
393            payload: packet.payload().to_vec(),
394        }
395    }
396    pub fn from_bytes(packet: &[u8]) -> TcpPacket {
397        let tcp_packet = pnet::packet::tcp::TcpPacket::new(packet).unwrap();
398        TcpPacket::from_pnet_packet(&tcp_packet)
399    }
400}
401
402pub(crate) fn build_tcp_packet(
403    tcp_packet: &mut pnet::packet::tcp::MutableTcpPacket,
404    src_ip: IpAddr,
405    src_port: u16,
406    dst_ip: IpAddr,
407    dst_port: u16,
408) {
409    tcp_packet.set_source(src_port);
410    tcp_packet.set_destination(dst_port);
411    tcp_packet.set_window(64240);
412    tcp_packet.set_data_offset(8);
413    tcp_packet.set_urgent_ptr(0);
414    tcp_packet.set_sequence(0);
415    tcp_packet.set_options(&[
416        pnet::packet::tcp::TcpOption::mss(1460),
417        pnet::packet::tcp::TcpOption::sack_perm(),
418        pnet::packet::tcp::TcpOption::nop(),
419        pnet::packet::tcp::TcpOption::nop(),
420        pnet::packet::tcp::TcpOption::wscale(7),
421    ]);
422    tcp_packet.set_flags(pnet::packet::tcp::TcpFlags::SYN);
423    match src_ip {
424        IpAddr::V4(src_ip) => match dst_ip {
425            IpAddr::V4(dst_ip) => {
426                let checksum =
427                    pnet::packet::tcp::ipv4_checksum(&tcp_packet.to_immutable(), &src_ip, &dst_ip);
428                tcp_packet.set_checksum(checksum);
429            }
430            IpAddr::V6(_) => {}
431        },
432        IpAddr::V6(src_ip) => match dst_ip {
433            IpAddr::V4(_) => {}
434            IpAddr::V6(dst_ip) => {
435                let checksum =
436                    pnet::packet::tcp::ipv6_checksum(&tcp_packet.to_immutable(), &src_ip, &dst_ip);
437                tcp_packet.set_checksum(checksum);
438            }
439        },
440    }
441}
442
443/// TCP Packet Builder
444#[derive(Clone, Debug)]
445pub struct TcpPacketBuilder {
446    /// Source IP address
447    pub src_ip: IpAddr,
448    /// Source port
449    pub src_port: u16,
450    /// Destination IP address
451    pub dst_ip: IpAddr,
452    /// Destination port
453    pub dst_port: u16,
454    /// Window size
455    pub window: u16,
456    /// TCP flags
457    pub flags: Vec<TcpFlag>,
458    /// TCP options
459    pub options: Vec<TcpOption>,
460    /// TCP payload
461    pub payload: Vec<u8>,
462}
463
464impl TcpPacketBuilder {
465    /// Constructs a new TcpPacketBuilder from Source SocketAddr and Destination SocketAddr with default options.
466    pub fn new(src_addr: SocketAddr, dst_addr: SocketAddr) -> TcpPacketBuilder {
467        TcpPacketBuilder {
468            src_ip: src_addr.ip(),
469            src_port: src_addr.port(),
470            dst_ip: dst_addr.ip(),
471            dst_port: dst_addr.port(),
472            window: 64240,
473            flags: vec![TcpFlag::Syn],
474            options: vec![
475                TcpOption::mss(1460),
476                TcpOption::sack_perm(),
477                TcpOption::nop(),
478                TcpOption::nop(),
479                TcpOption::wscale(7),
480            ],
481            payload: vec![],
482        }
483    }
484    /// Build a TCP packet and return bytes
485    pub fn build(&self) -> Vec<u8> {
486        let data_offset = get_tcp_data_offset(self.options.clone());
487        let tcp_options_len = get_tcp_options_length(data_offset);
488        let mut buffer: Vec<u8> = vec![0; TCP_HEADER_LEN + tcp_options_len + self.payload.len()];
489        let mut tcp_packet = pnet::packet::tcp::MutableTcpPacket::new(&mut buffer).unwrap();
490        tcp_packet.set_source(self.src_port);
491        tcp_packet.set_destination(self.dst_port);
492        tcp_packet.set_window(self.window);
493        tcp_packet.set_data_offset(data_offset);
494        tcp_packet.set_urgent_ptr(0);
495        tcp_packet.set_sequence(0);
496        let mut tcp_flags: u8 = 0;
497        for flag in &self.flags {
498            if tcp_flags == 0 {
499                tcp_flags = flag.number();
500            } else {
501                tcp_flags |= flag.number();
502            }
503        }
504        tcp_packet.set_flags(tcp_flags);
505        let mut tcp_options: Vec<pnet::packet::tcp::TcpOption> = vec![];
506        for opt in &self.options {
507            tcp_options.push(opt.to_pnet_type());
508        }
509        tcp_packet.set_options(&tcp_options);
510        if self.payload.len() > 0 {
511            tcp_packet.set_payload(&self.payload);
512        }
513        match self.src_ip {
514            IpAddr::V4(src_ip) => match self.dst_ip {
515                IpAddr::V4(dst_ip) => {
516                    let checksum = pnet::packet::tcp::ipv4_checksum(
517                        &tcp_packet.to_immutable(),
518                        &src_ip,
519                        &dst_ip,
520                    );
521                    tcp_packet.set_checksum(checksum);
522                }
523                IpAddr::V6(_) => {}
524            },
525            IpAddr::V6(src_ip) => match self.dst_ip {
526                IpAddr::V4(_) => {}
527                IpAddr::V6(dst_ip) => {
528                    let checksum = pnet::packet::tcp::ipv6_checksum(
529                        &tcp_packet.to_immutable(),
530                        &src_ip,
531                        &dst_ip,
532                    );
533                    tcp_packet.set_checksum(checksum);
534                }
535            },
536        }
537        tcp_packet.packet().to_vec()
538    }
539}