Skip to main content

manycastr/net/
tcp.rs

1use crate::custom_module::manycastr::{Address, address};
2use crate::net::{IPv4Packet, IPv6Packet, PacketPayload, PseudoHeader, calculate_checksum};
3use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
4use std::io::{Cursor, Write};
5
6/// A TCPPacket <https://en.wikipedia.org/wiki/Transmission_Control_Protocol>
7#[derive(Debug)]
8pub struct TCPPacket {
9    pub sport: u16,
10    pub dport: u16,
11    pub seq: u32,
12    pub ack: u32,
13    // offset and reserved are combined into a single u8 (reserved is all 0's)
14    pub offset: u8,
15    pub flags: u8,
16    pub window_size: u16,
17    pub checksum: u16,
18    pub pointer: u16,
19    pub body: Vec<u8>,
20}
21
22/// Parsing from bytes to TCPPacket
23impl From<&[u8]> for TCPPacket {
24    fn from(data: &[u8]) -> Self {
25        let mut data = Cursor::new(data);
26        TCPPacket {
27            sport: data.read_u16::<NetworkEndian>().unwrap(),
28            dport: data.read_u16::<NetworkEndian>().unwrap(),
29            seq: data.read_u32::<NetworkEndian>().unwrap(),
30            ack: data.read_u32::<NetworkEndian>().unwrap(),
31            offset: data.read_u8().unwrap(),
32            flags: data.read_u8().unwrap(),
33            window_size: data.read_u16::<NetworkEndian>().unwrap(),
34            checksum: data.read_u16::<NetworkEndian>().unwrap(),
35            pointer: data.read_u16::<NetworkEndian>().unwrap(),
36            body: data.into_inner()[8..].to_vec(),
37        }
38    }
39}
40
41impl From<&TCPPacket> for Vec<u8> {
42    fn from(packet: &TCPPacket) -> Self {
43        let mut wtr = vec![];
44        wtr.write_u16::<NetworkEndian>(packet.sport)
45            .expect("Unable to write to byte buffer for TCP packet");
46        wtr.write_u16::<NetworkEndian>(packet.dport)
47            .expect("Unable to write to byte buffer for TCP packet");
48        wtr.write_u32::<NetworkEndian>(packet.seq)
49            .expect("Unable to write to byte buffer for TCP packet");
50        wtr.write_u32::<NetworkEndian>(packet.ack)
51            .expect("Unable to write to byte buffer for TCP packet");
52        wtr.write_u8(packet.offset)
53            .expect("Unable to write to byte buffer for TCP packet");
54        wtr.write_u8(packet.flags)
55            .expect("Unable to write to byte buffer for TCP packet");
56        wtr.write_u16::<NetworkEndian>(packet.window_size)
57            .expect("Unable to write to byte buffer for TCP packet");
58        wtr.write_u16::<NetworkEndian>(packet.checksum)
59            .expect("Unable to write to byte buffer for TCP packet");
60        wtr.write_u16::<NetworkEndian>(packet.pointer)
61            .expect("Unable to write to byte buffer for TCP packet");
62        wtr.write_all(&packet.body)
63            .expect("Unable to write to byte buffer for TCP packet");
64
65        wtr
66    }
67}
68
69impl TCPPacket {
70    /// Create a basic TCP SYN/ACK packet with checksum
71    pub fn tcp_syn_ack(
72        src: &Address,
73        dst: &Address,
74        sport: u16,
75        dport: u16,
76        ack: u32,
77        ttl: u8,
78        info_url: Option<&str>,
79    ) -> Vec<u8> {
80        let body: Vec<u8> = if let Some(info_url) = info_url {
81            info_url.bytes().collect()
82        } else {
83            vec![]
84        };
85
86        let mut tcp_packet = Self {
87            sport,
88            dport,
89            seq: 0, // Sequence number is not reflected
90            ack,
91            offset: 0b01010000, // Offset 5 for minimum TCP header length (0101) + 0000 for reserved
92            flags: 0b00010010,  // SYN and ACK flags
93            checksum: 0,
94            pointer: 0,
95            body,
96            window_size: 0,
97        };
98
99        // Turn everything into a vec of bytes and calculate checksum
100        let tcp_bytes: Vec<u8> = (&tcp_packet).into();
101
102        let pseudo_header = PseudoHeader::new(src, dst, 6, tcp_bytes.len() as u32);
103        tcp_packet.checksum = calculate_checksum(&tcp_bytes, &pseudo_header);
104
105        match (&src.value, &dst.value) {
106            (Some(address::Value::V6(_)), Some(address::Value::V6(_))) => {
107                let v6_packet = IPv6Packet {
108                    payload_length: tcp_bytes.len() as u16,
109                    flow_label: 15037,
110                    next_header: 6, // TCP
111                    hop_limit: ttl,
112                    src: src.into(),
113                    dst: dst.into(),
114                    payload: PacketPayload::Tcp { value: tcp_packet },
115                };
116                (&v6_packet).into()
117            }
118            (Some(address::Value::V4(_)), Some(address::Value::V4(_))) => {
119                let v4_packet = IPv4Packet {
120                    length: 20 + tcp_bytes.len() as u16,
121                    identifier: 15037,
122                    ttl,
123                    src: src.into(),
124                    dst: dst.into(),
125                    payload: PacketPayload::Tcp { value: tcp_packet },
126                };
127                (&v4_packet).into()
128            }
129            _ => panic!("IP version mismatch or invalid address in tcp_syn_ack"),
130        }
131    }
132}