#include "VpnPacket.hpp" #include "VpnPeer.hpp" #include #include const size_t VpnPacket::VPN_HEADER_BYTES = 8; const size_t VpnPacket::TLV_HEADER_BYTES = 3; static const size_t OUTER_HEADERS_BYTES = 40 /* IPv6 header */ + 8 /* UDP header */; // We use a TUN device, hence we don't have a layer 2 header. static const int DATA_SEQNO_POS = 0, DATA_TIMESTAMP_POS = 4; VpnPacket::VpnPacket(size_t mtu) : _peer(nullptr), _data_space(mtu-OUTER_HEADERS_BYTES), _data_size(VPN_HEADER_BYTES), _reception_timestamp(0) { _data = new char[mtu - OUTER_HEADERS_BYTES]; } VpnPacket::~VpnPacket() { delete[] _data; } VpnPacketTLV VpnPacket::first_tlv() { return VpnPacketTLV(*this, 0); } size_t VpnPacket::get_tunnelled_mtu(size_t udp_mtu) { return udp_mtu - OUTER_HEADERS_BYTES - VPN_HEADER_BYTES - TLV_HEADER_BYTES; } 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::steady_clock::now()).time_since_epoch().count(); } void VpnPacket::upon_reception() { _reception_timestamp = std::chrono::time_point_cast( std::chrono::steady_clock::now()).time_since_epoch().count(); } uint32_t VpnPacket::next_seqno() { if(!_peer) throw PeerNotSet(); return _peer->next_seqno(); } VpnPacketTLV::VpnPacketTLV(VpnPacket& packet, size_t payload_offset) : _packet(packet), _tlv_pos(payload_offset) {} VpnPacketTLV::VpnPacketTLV(const VpnPacketTLV& other) : _packet(other._packet), _tlv_pos(other._tlv_pos) {} 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; } VpnPacketTLV VpnPacketTLV::next_tlv() { size_t next_offset = _tlv_pos + get_payload_size(); return VpnPacketTLV(_packet, next_offset); } void VpnPacketTLV::seek_next_tlv() { _tlv_pos = _tlv_pos + VpnPacket::TLV_HEADER_BYTES + get_payload_size(); } 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); } uint16_t VpnPacketTLV::get_payload_space() const { return _packet.get_payload_space() - _packet.get_payload_size() + get_payload_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); } bool TunnelledPacket::parse_as_ipv6() { return parse_ipv6_header(get_payload(), get_payload_size(), _ipv6_header); }