Repository navigation
Expand file tree
/
Copy pathtcp.cpp
More file actions
119 lines (102 loc) · 4.39 KB
/
Copy pathtcp.cpp
File metadata and controls
119 lines (102 loc) · 4.39 KB
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "include/tcp.hpp"
#include "include/ipv4.hpp"
#include "include/parsing.hpp"
#include <cassert>
#include <cstdint>
#include <iostream>
#include <optional>
#include <span>
#include <unistd.h>
#include <vector>
// https://datatracker.ietf.org/doc/html/rfc9293
TcpPacket::TcpPacket(std::span<const uint8_t> packet)
: source_port(read_u16(packet, 0)), destination_port(read_u16(packet, 2)),
seq(read_u32(packet, 4)), ack(read_u32(packet, 8)), doffset_rsrvd(packet[12]),
control_flags(static_cast<unsigned long long>(packet[13])), window(read_u16(packet, 14)),
checksum(read_u16(packet, 16)), urgent_ptr(read_u16(packet, 18)) {
int doffset{doffset_rsrvd >> 4};
if (doffset > 5) {
options = std::optional<std::span<const uint8_t>>{packet.subspan(20, (doffset * 4) - 20)};
} else {
options = std::nullopt;
}
std::cout << doffset << packet.size() << std::endl;
data = packet.subspan(doffset * 4);
}
// the ISN is randomly set so that you can't just inject arbitrary TCP data also so that you can't
// ghost packets
void TcpPacket::print_seq() {
if (this->syn()) {
std::cout << std::format("SYN set, ISN: {}\n", seq);
} else {
std::cout << std::format("seq: {}\n", seq);
}
}
std::vector<uint8_t> TcpPacket::to_bytes() const&& {
BufWriter w = BufWriter();
w.write(this->source_port);
w.write(this->destination_port);
w.write(this->seq);
w.write(this->ack);
w.write(this->doffset_rsrvd);
w.write(static_cast<uint8_t>(this->control_flags.to_ulong()));
w.write(this->window);
w.write(this->checksum);
w.write(this->urgent_ptr);
w.write(this->data);
return std::move(w).finish();
}
// Create a TcpPacket and define some things in the header
TcpPacket::TcpPacket(uint16_t src_port, uint16_t dst_port, uint32_t window, uint32_t seq)
: source_port(src_port), destination_port(dst_port), seq(seq), window(window) {
doffset_rsrvd = (5) << 4; // there are no options
}
std::span<const uint8_t> TcpPacket::get_data() const { return data; }
bool TcpPacket::syn() const { return control_flags[1]; }
void TcpPacket::set_syn() { control_flags.set(1); }
int TcpPacket::get_seq() const { return seq; }
int TcpPacket::get_window() const { return window; }
// set's ack flag and the ack field
void TcpPacket::set_ack(uint32_t ack) {
control_flags.set(4);
this->ack = ack;
}
int TcpPacket::get_destination_port() const { return destination_port; }
int TcpPacket::get_source_port() const { return source_port; }
TCB::TCB(RecieveSequenceSpace r, SendSequenceSpace s) : state(State::SynRcvd), sss(s), rss(r) {}
std::optional<TCB> TCB::accept(int fd, const IPv4Packet ip, const TcpPacket tcp) {
if (tcp.syn()) {
// NOTE: make sure we don't allocate any local state until a connection is ESTAB to
// prevent SYN flood attacks
// sender (client) info
auto rss = RecieveSequenceSpace(tcp.get_seq() + 1, tcp.get_window(), 0, tcp.get_seq());
// our (server) info
auto sss = SendSequenceSpace();
sss.iss = 0;
sss.una = sss.iss;
sss.nxt = sss.una + 1;
sss.wnd = 16348; // just an agreed upon default
// don't care about wl1, wl2 for now
TcpPacket syn_ack =
TcpPacket(tcp.get_destination_port(), tcp.get_source_port(), sss.wnd,
sss.iss); // HACK: update this to be random so we can tell if we have a
// duplicate connection and respond appropriately otherwise seq
// might overlap and we get confused but cpp random numbers are
syn_ack.set_syn();
syn_ack.set_ack(rss.nxt); // ack == next octet we expect to recieve
std::vector<uint8_t> tcp_packet = std::move(syn_ack).to_bytes();
std::vector<uint8_t> response{0x00, 0x00, 0x00, 0x02};
IPv4Packet ip_header = IPv4Packet(tcp_packet.size(), ip.destination(), ip.source(), 64,
6); // tcp protocol = 6
ip_header.set_body(tcp_packet);
std::vector<uint8_t> ip_packet = std::move(ip_header).to_bytes();
response.insert(response.end(), ip_packet.begin(), ip_packet.end());
write(fd, ip_packet.data(), ip_packet.size());
return TCB(rss, sss);
} else {
return std::nullopt;
}
}
std::optional<TCB> TCB::on_packet(int fd, const IPv4Packet ip, const TcpPacket tcp) {
assert(false);
}