From 79dbf2378420190aa5220f82469290f6dd39ce2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Bastian?= Date: Tue, 16 Jun 2020 18:57:08 +0200 Subject: [PATCH] Set tun MTU based on VpnPacket max payload --- TunDevice.cpp | 25 +++++++++++++++++++++++++ TunDevice.hpp | 6 ++++++ UdpVpn.cpp | 1 + VpnPacket.cpp | 4 ++++ VpnPacket.hpp | 3 +++ 5 files changed, 39 insertions(+) diff --git a/TunDevice.cpp b/TunDevice.cpp index 33bf0a1..2767811 100644 --- a/TunDevice.cpp +++ b/TunDevice.cpp @@ -72,6 +72,31 @@ TunDevice::~TunDevice() { close(_fd); } +uint16_t TunDevice::get_mtu() const { + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // Any socket will do + + struct ifreq ifr; + ifr.ifr_addr.sa_family = AF_INET6; + strncpy(ifr.ifr_name, _dev_name.c_str(), sizeof(ifr.ifr_name)-1); + if (ioctl(sockfd, SIOCGIFMTU, (caddr_t)&ifr) < 0) + return 0; + close(sockfd); + return ifr.ifr_mtu; +} + +bool TunDevice::set_mtu(uint16_t mtu) { + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // Any socket will do + + struct ifreq ifr; + ifr.ifr_addr.sa_family = AF_INET6; + strncpy(ifr.ifr_name, _dev_name.c_str(), sizeof(ifr.ifr_name)-1); + ifr.ifr_mtu = mtu; + if (ioctl(sockfd, SIOCSIFMTU, (caddr_t)&ifr) < 0) + return false; + close(sockfd); + return true; +} + size_t TunDevice::poll_packet(char* read_buffer, size_t buf_size, int timeout) { int poll_rc = poll(&_poll_fd, 1, timeout); if(poll_rc < 0) { diff --git a/TunDevice.hpp b/TunDevice.hpp index a81b914..0df8b71 100644 --- a/TunDevice.hpp +++ b/TunDevice.hpp @@ -29,6 +29,12 @@ class TunDevice { const std::string& get_dev_name() const { return _dev_name; } int get_fd() const { return _fd; } + /** Get the interface's MTU */ + uint16_t get_mtu() const; + + /** Set the interface's MTU */ + bool set_mtu(uint16_t mtu); + /* Reads a packet from the device. * Timeouts after `timeout` ms, or never if `timeout < 0`. * Upon timeout, returns 0. diff --git a/UdpVpn.cpp b/UdpVpn.cpp index 6a0d4bd..1b6b2c3 100644 --- a/UdpVpn.cpp +++ b/UdpVpn.cpp @@ -16,6 +16,7 @@ static const size_t VPN_MTU = 1460; // TODO determine this -- issue #3 UdpVpn::UdpVpn() : _stopped(false), _vpn_mtu(VPN_MTU), _tun_dev("cvpn%d"), _peer(nullptr) { + _tun_dev.set_mtu(VpnPacket::get_tunnelled_mtu(_vpn_mtu)); _socket = socket(AF_INET6, SOCK_DGRAM, 0); if(_socket < 0) throw UdpVpn::InitializationError("Cannot create socket", errno, true); diff --git a/VpnPacket.cpp b/VpnPacket.cpp index 3dfcf61..f003dd4 100644 --- a/VpnPacket.cpp +++ b/VpnPacket.cpp @@ -30,6 +30,10 @@ VpnPacketTLV VpnPacket::first_tlv() { return VpnPacketTLV(*this, 0); } +size_t VpnPacket::get_tunnelled_mtu(size_t udp_mtu) { + return udp_mtu - VPN_HEADER_BYTES - TLV_HEADER_BYTES; +} + uint32_t VpnPacket::get_seqno() const { return *(uint32_t*)(_data + DATA_SEQNO_POS); } diff --git a/VpnPacket.hpp b/VpnPacket.hpp index f4df618..dfa3284 100644 --- a/VpnPacket.hpp +++ b/VpnPacket.hpp @@ -56,6 +56,9 @@ class VpnPacket { VpnPacketTLV first_tlv(); + /// Get the maximal payload space for a given tunnel MTU + static size_t get_tunnelled_mtu(size_t udp_mtu); + /// Set packet peer -- used for sequence numbers void set_peer(VpnPeer* peer) { _peer = peer; }