xenet_packet_builder/
tcp.rs

1use std::net::{IpAddr, SocketAddr};
2use xenet_packet::ethernet::ETHERNET_HEADER_LEN;
3use xenet_packet::ipv4::IPV4_HEADER_LEN;
4use xenet_packet::ipv6::IPV6_HEADER_LEN;
5use xenet_packet::tcp::TCP_MIN_DATA_OFFSET;
6use xenet_packet::tcp::{MutableTcpPacket, TcpFlags, TcpOption, TCP_HEADER_LEN};
7use xenet_packet::Packet;
8
9/// Default TCP Option Length.
10pub const TCP_DEFAULT_OPTION_LEN: usize = 12;
11/// Default TCP Source Port.
12pub const DEFAULT_SRC_PORT: u16 = 53443;
13/// TCP (IPv4) Minimum Packet Length.
14pub const TCPV4_MINIMUM_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV4_HEADER_LEN + TCP_HEADER_LEN;
15/// TCP (IPv4) Default Packet Length.
16pub const TCPV4_DEFAULT_PACKET_LEN: usize =
17    ETHERNET_HEADER_LEN + IPV4_HEADER_LEN + TCP_HEADER_LEN + TCP_DEFAULT_OPTION_LEN;
18/// TCP (IPv4) Minimum IP Packet Length.
19pub const TCPV4_MINIMUM_IP_PACKET_LEN: usize = IPV4_HEADER_LEN + TCP_HEADER_LEN;
20/// TCP (IPv4) Default IP Packet Length.
21pub const TCPV4_DEFAULT_IP_PACKET_LEN: usize =
22    IPV4_HEADER_LEN + TCP_HEADER_LEN + TCP_DEFAULT_OPTION_LEN;
23/// TCP (IPv6) Minimum Packet Length.
24pub const TCPV6_MINIMUM_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + TCP_HEADER_LEN;
25/// TCP (IPv6) Default Packet Length.
26pub const TCPV6_DEFAULT_PACKET_LEN: usize =
27    ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + TCP_HEADER_LEN + TCP_DEFAULT_OPTION_LEN;
28/// TCP (IPv6) Minimum IP Packet Length.
29pub const TCPV6_MINIMUM_IP_PACKET_LEN: usize = IPV6_HEADER_LEN + TCP_HEADER_LEN;
30/// TCP (IPv6) Default IP Packet Length.
31pub const TCPV6_DEFAULT_IP_PACKET_LEN: usize =
32    IPV6_HEADER_LEN + TCP_HEADER_LEN + TCP_DEFAULT_OPTION_LEN;
33
34/// Get the length of TCP options from TCP data offset.
35pub fn get_tcp_options_length(data_offset: u8) -> usize {
36    if data_offset > 5 {
37        data_offset as usize * 4 - TCP_HEADER_LEN
38    } else {
39        0
40    }
41}
42
43/// Get the TCP data offset from TCP options.
44pub fn get_tcp_data_offset(opstions: Vec<TcpOption>) -> u8 {
45    let mut total_size: u8 = 0;
46    for opt in opstions {
47        total_size += opt.kind().size() as u8;
48    }
49    if total_size % 4 == 0 {
50        total_size / 4 + TCP_MIN_DATA_OFFSET
51    } else {
52        total_size / 4 + TCP_MIN_DATA_OFFSET + 1
53    }
54}
55
56pub(crate) fn build_tcp_packet(
57    tcp_packet: &mut MutableTcpPacket,
58    src_ip: IpAddr,
59    src_port: u16,
60    dst_ip: IpAddr,
61    dst_port: u16,
62) {
63    tcp_packet.set_source(src_port);
64    tcp_packet.set_destination(dst_port);
65    tcp_packet.set_window(64240);
66    tcp_packet.set_data_offset(8);
67    tcp_packet.set_urgent_ptr(0);
68    tcp_packet.set_sequence(0);
69    tcp_packet.set_options(&[
70        TcpOption::mss(1460),
71        TcpOption::sack_perm(),
72        TcpOption::nop(),
73        TcpOption::nop(),
74        TcpOption::wscale(7),
75    ]);
76    tcp_packet.set_flags(TcpFlags::SYN);
77    match src_ip {
78        IpAddr::V4(src_ip) => match dst_ip {
79            IpAddr::V4(dst_ip) => {
80                let checksum =
81                    xenet_packet::tcp::ipv4_checksum(&tcp_packet.to_immutable(), &src_ip, &dst_ip);
82                tcp_packet.set_checksum(checksum);
83            }
84            IpAddr::V6(_) => {}
85        },
86        IpAddr::V6(src_ip) => match dst_ip {
87            IpAddr::V4(_) => {}
88            IpAddr::V6(dst_ip) => {
89                let checksum =
90                    xenet_packet::tcp::ipv6_checksum(&tcp_packet.to_immutable(), &src_ip, &dst_ip);
91                tcp_packet.set_checksum(checksum);
92            }
93        },
94    }
95}
96
97/// TCP Packet Builder.
98#[derive(Clone, Debug)]
99pub struct TcpPacketBuilder {
100    /// Source IP address.
101    pub src_ip: IpAddr,
102    /// Source port.
103    pub src_port: u16,
104    /// Destination IP address.
105    pub dst_ip: IpAddr,
106    /// Destination port.
107    pub dst_port: u16,
108    /// Window size.
109    pub window: u16,
110    /// TCP flags.
111    pub flags: u8,
112    /// TCP options.
113    pub options: Vec<TcpOption>,
114    /// TCP payload.
115    pub payload: Vec<u8>,
116}
117
118impl TcpPacketBuilder {
119    /// Constructs a new TcpPacketBuilder from Source SocketAddr and Destination SocketAddr with default options.
120    pub fn new(src_addr: SocketAddr, dst_addr: SocketAddr) -> TcpPacketBuilder {
121        TcpPacketBuilder {
122            src_ip: src_addr.ip(),
123            src_port: src_addr.port(),
124            dst_ip: dst_addr.ip(),
125            dst_port: dst_addr.port(),
126            window: 64240,
127            flags: TcpFlags::SYN,
128            options: vec![
129                TcpOption::mss(1460),
130                TcpOption::sack_perm(),
131                TcpOption::nop(),
132                TcpOption::nop(),
133                TcpOption::wscale(7),
134            ],
135            payload: vec![],
136        }
137    }
138    /// Build a TCP packet and return bytes.
139    pub fn build(&self) -> Vec<u8> {
140        let data_offset = get_tcp_data_offset(self.options.clone());
141        let tcp_options_len = get_tcp_options_length(data_offset);
142        let mut buffer: Vec<u8> = vec![0; TCP_HEADER_LEN + tcp_options_len + self.payload.len()];
143        let mut tcp_packet = MutableTcpPacket::new(&mut buffer).unwrap();
144        tcp_packet.set_source(self.src_port);
145        tcp_packet.set_destination(self.dst_port);
146        tcp_packet.set_window(self.window);
147        tcp_packet.set_data_offset(data_offset);
148        tcp_packet.set_urgent_ptr(0);
149        tcp_packet.set_sequence(0);
150        tcp_packet.set_flags(self.flags);
151        tcp_packet.set_options(&self.options);
152        if self.payload.len() > 0 {
153            tcp_packet.set_payload(&self.payload);
154        }
155        match self.src_ip {
156            IpAddr::V4(src_ip) => match self.dst_ip {
157                IpAddr::V4(dst_ip) => {
158                    let checksum = xenet_packet::tcp::ipv4_checksum(
159                        &tcp_packet.to_immutable(),
160                        &src_ip,
161                        &dst_ip,
162                    );
163                    tcp_packet.set_checksum(checksum);
164                }
165                IpAddr::V6(_) => {}
166            },
167            IpAddr::V6(src_ip) => match self.dst_ip {
168                IpAddr::V4(_) => {}
169                IpAddr::V6(dst_ip) => {
170                    let checksum = xenet_packet::tcp::ipv6_checksum(
171                        &tcp_packet.to_immutable(),
172                        &src_ip,
173                        &dst_ip,
174                    );
175                    tcp_packet.set_checksum(checksum);
176                }
177            },
178        }
179        tcp_packet.packet().to_vec()
180    }
181}