-
Notifications
You must be signed in to change notification settings - Fork 2
/
SimplePacketCrafter.h
120 lines (112 loc) · 4.17 KB
/
SimplePacketCrafter.h
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
120
#ifndef LIB_OPEN_VPN_SIMPLE_PACKET_CRAFTER_H
#define LIB_OPEN_VPN_SIMPLE_PACKET_CRAFTER_H
#include <memory>
#include <string>
#include <openvpn/buffer/buffer.hpp>
#include <openvpn/ip/ipcommon.hpp>
#include "tins/tins.h"
//Header + payload maximum size for maximum packet IPV4 or IPV6
const int IP_PACKET_MAX_SIZE = 65535 + 40;
class SimplePacketCrafter
{
public:
void setSourceIPV4(std::string address)
{
ipv4address = address;
}
void setSourceIPV6(std::string address)
{
ipv6address = address;
}
//TODO: should I parse the packet here to see if it's really an IP packet?
//TODO: multiple optimizations here (no libtins and use stack of size max of ip packet size)
static bool replaceSourceAddress(uint8_t *packet, size_t size, std::string sourceAddress)
{
if (size==0) {
throw std::runtime_error("replaceSourceAddress exception: empty packet");
}
Tins::IP tins_packet = Tins::IP(packet, size);
tins_packet.src_addr(sourceAddress);
auto serialized_tins_packet = tins_packet.serialize();
size_t tins_packet_size = serialized_tins_packet.size();
if (size!=tins_packet_size) {
throw std::runtime_error("size of tins packet and original packet differ");
}
for (size_t i = 0; i < size; i++)
{
packet[i] = serialized_tins_packet[i];
}
return true;
}
static bool replaceDestinationAddress(uint8_t *packet, size_t size, std::string destinationAddressIpv4, std::string destinationAddressIpv6)
{
if (size==0) {
throw std::runtime_error("replaceSourceAddress exception: empty packet");
}
Tins::IP tins_packet = Tins::IP(packet, size);
if (tins_packet.version()==4) {
if (destinationAddressIpv4.empty()) {
throw std::runtime_error("replaceDestinationAddress exception: tried to fill ipv6 packet but destinationAddressIpv6 is empty");
}
tins_packet.dst_addr(destinationAddressIpv4);
} else if (tins_packet.version()==6) {
if (destinationAddressIpv6.empty()) {
throw std::runtime_error("replaceDestinationAddress exception: tried to fill ipv6 packet but destinationAddressIpv6 is empty");
}
tins_packet.dst_addr(destinationAddressIpv6);
}
auto serialized_tins_packet = tins_packet.serialize();
size_t tins_packet_size = serialized_tins_packet.size();
if (size!=tins_packet_size) {
throw std::runtime_error("size of tins packet and original packet differ");
}
for (size_t i = 0; i < size; i++)
{
packet[i] = serialized_tins_packet[i];
}
return true;
}
void fillIPSource(openvpn::BufferAllocated &buf)
{
if (buf.size()<1) {
throw std::runtime_error("fillIPSource exception: buffer empty");
}
int ipVersion = openvpn::IPCommon::version(buf[0]);
if (ipv4address.size() > IP_PACKET_MAX_SIZE || ipv6address.size() > IP_PACKET_MAX_SIZE)
{
throw std::runtime_error("ipv4/6address size too big");
}
if (ipVersion == 4)
{
const unsigned int ipv4HeaderSize = 32;
if (!ipv4address.empty() && buf.size() > ipv4HeaderSize)
{
replaceSourceAddress(buf.data(), buf.size(), ipv4address);
}
else
{
throw std::runtime_error("ipv4address empty or buf with small size");
}
}
else if (ipVersion == 6)
{
const unsigned int ipv6HeaderSize = 288;
if (!ipv6address.empty() && buf.size() > ipv6HeaderSize)
{
replaceSourceAddress(buf.data(), buf.size(), ipv4address);
}
else
{
throw std::runtime_error("ipv6address empty or buf with small size");
}
}
else
{
throw std::runtime_error("couldn't detect ip version of buffer");
}
}
private:
std::string ipv4address;
std::string ipv6address;
};
#endif //LIB_OPEN_VPN_SIMPLE_PACKET_CRAFTER_H