2020-06-05 17:30:35 +02:00
|
|
|
#include "VpnPacket.hpp"
|
2020-06-10 18:49:36 +02:00
|
|
|
#include "VpnPeer.hpp"
|
2020-06-05 17:30:35 +02:00
|
|
|
|
2020-06-10 18:49:36 +02:00
|
|
|
#include <chrono>
|
2020-06-12 17:36:55 +02:00
|
|
|
#include <cstring>
|
2020-06-05 17:30:35 +02:00
|
|
|
|
2020-06-10 18:49:36 +02:00
|
|
|
const size_t VpnPacket::VPN_HEADER_BYTES = 8;
|
2020-06-12 17:36:55 +02:00
|
|
|
const size_t VpnPacket::TLV_HEADER_BYTES = 3;
|
2020-06-10 18:49:36 +02:00
|
|
|
uint32_t VpnPacket::_next_general_seqno = 0;
|
|
|
|
|
|
|
|
static const size_t OUTER_HEADERS_BYTES =
|
2020-06-05 17:30:35 +02:00
|
|
|
40 /* IPv6 header */ + 8 /* UDP header */;
|
|
|
|
// We use a TUN device, hence we don't have a layer 2 header.
|
|
|
|
|
2020-06-10 18:49:36 +02:00
|
|
|
static const int
|
|
|
|
DATA_SEQNO_POS = 0,
|
|
|
|
DATA_TIMESTAMP_POS = 4;
|
|
|
|
|
2020-06-05 17:30:35 +02:00
|
|
|
VpnPacket::VpnPacket(size_t mtu)
|
2020-06-12 17:36:55 +02:00
|
|
|
: _peer(nullptr), _data_space(mtu-OUTER_HEADERS_BYTES),
|
|
|
|
_data_size(VPN_HEADER_BYTES), _reception_timestamp(0)
|
2020-06-05 17:30:35 +02:00
|
|
|
{
|
2020-06-10 18:49:36 +02:00
|
|
|
_data = new char[mtu - OUTER_HEADERS_BYTES];
|
2020-06-05 17:30:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
VpnPacket::~VpnPacket() {
|
|
|
|
delete[] _data;
|
|
|
|
}
|
|
|
|
|
2020-06-12 17:36:55 +02:00
|
|
|
VpnPacket::iterator VpnPacket::begin() {
|
|
|
|
return iterator(VpnPacketTLV(*this, 0));
|
|
|
|
}
|
|
|
|
VpnPacket::iterator VpnPacket::end() {
|
|
|
|
return iterator(VpnPacketTLV(*this, get_payload_size()));
|
|
|
|
}
|
|
|
|
|
2020-06-05 17:30:35 +02:00
|
|
|
bool VpnPacket::parse_as_ipv6() {
|
|
|
|
return parse_ipv6_header(get_payload(), get_payload_size(), _ipv6_header);
|
|
|
|
}
|
2020-06-10 18:49:36 +02:00
|
|
|
|
|
|
|
uint32_t VpnPacket::get_seqno() const {
|
|
|
|
return *(uint32_t*)(_data + DATA_SEQNO_POS);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t VpnPacket::get_sending_timestamp() const {
|
|
|
|
return *(uint32_t*)(_data + DATA_TIMESTAMP_POS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VpnPacket::prepare_for_sending() {
|
|
|
|
*(uint32_t*)(_data + DATA_SEQNO_POS) = next_seqno();
|
|
|
|
*(uint32_t*)(_data + DATA_TIMESTAMP_POS) =
|
|
|
|
std::chrono::time_point_cast<std::chrono::microseconds>(
|
|
|
|
std::chrono::steady_clock::now()).time_since_epoch().count();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VpnPacket::upon_reception() {
|
|
|
|
_reception_timestamp =
|
|
|
|
std::chrono::time_point_cast<std::chrono::microseconds>(
|
|
|
|
std::chrono::steady_clock::now()).time_since_epoch().count();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t VpnPacket::next_seqno() {
|
|
|
|
if(_peer)
|
|
|
|
return _peer->next_seqno();
|
|
|
|
return _next_general_seqno++;
|
|
|
|
}
|
2020-06-12 17:36:55 +02:00
|
|
|
|
|
|
|
|
|
|
|
VpnPacketTLV::VpnPacketTLV(VpnPacket& packet, size_t payload_offset)
|
|
|
|
: _packet(packet), _tlv_pos(payload_offset)
|
|
|
|
{}
|
|
|
|
|
|
|
|
VpnPacketTLV VpnPacketTLV::create(
|
|
|
|
VpnPacket& packet, VpnPacket::PayloadType type)
|
|
|
|
{
|
|
|
|
VpnPacketTLV tlv = VpnPacketTLV(packet, packet.get_payload_size());
|
|
|
|
packet.increase_payload_size(VpnPacket::TLV_HEADER_BYTES);
|
|
|
|
|
|
|
|
char* data = tlv.get_data();
|
|
|
|
data[0] = type;
|
|
|
|
*(uint16_t*)(data+1) = 0; // Set len to 0
|
|
|
|
|
|
|
|
return tlv;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t VpnPacketTLV::get_payload_size() const {
|
|
|
|
return *(uint16_t*)(get_data() + 1);
|
|
|
|
}
|
|
|
|
void VpnPacketTLV::set_payload_size(uint16_t size) {
|
|
|
|
uint16_t* data_size_ptr = (uint16_t*)(get_data() + 1);
|
|
|
|
uint16_t old_size = *data_size_ptr;
|
|
|
|
*data_size_ptr = size;
|
|
|
|
_packet.increase_payload_size(size - old_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
VpnPacket::PayloadType VpnPacketTLV::get_type() const {
|
|
|
|
return (VpnPacket::PayloadType)(*(uint8_t*)(get_data()));
|
|
|
|
}
|
|
|
|
void VpnPacketTLV::set_type(VpnPacket::PayloadType type) {
|
|
|
|
*(uint8_t*)(get_data()) = (uint8_t) type;
|
|
|
|
}
|
|
|
|
|
|
|
|
TunnelledPacket::TunnelledPacket(VpnPacket& packet, size_t payload_offset)
|
|
|
|
: VpnPacketTLV(packet, payload_offset)
|
|
|
|
{}
|
|
|
|
|
|
|
|
TunnelledPacket::TunnelledPacket(const VpnPacketTLV& copy)
|
|
|
|
: VpnPacketTLV(copy._packet, copy._tlv_pos)
|
|
|
|
{}
|
|
|
|
|
|
|
|
TunnelledPacket TunnelledPacket::create(VpnPacket& packet) {
|
|
|
|
return VpnPacketTLV::create(packet, VpnPacket::PAYLOAD_TYPE_TUNNELLED);
|
|
|
|
}
|