Set tun MTU based on VpnPacket max payload

This commit is contained in:
Théophile Bastian 2020-06-16 18:57:08 +02:00
parent 94f42d08c0
commit 79dbf23784
5 changed files with 39 additions and 0 deletions

View file

@ -72,6 +72,31 @@ TunDevice::~TunDevice() {
close(_fd); 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) { size_t TunDevice::poll_packet(char* read_buffer, size_t buf_size, int timeout) {
int poll_rc = poll(&_poll_fd, 1, timeout); int poll_rc = poll(&_poll_fd, 1, timeout);
if(poll_rc < 0) { if(poll_rc < 0) {

View file

@ -29,6 +29,12 @@ class TunDevice {
const std::string& get_dev_name() const { return _dev_name; } const std::string& get_dev_name() const { return _dev_name; }
int get_fd() const { return _fd; } 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. /* Reads a packet from the device.
* Timeouts after `timeout` ms, or never if `timeout < 0`. * Timeouts after `timeout` ms, or never if `timeout < 0`.
* Upon timeout, returns 0. * Upon timeout, returns 0.

View file

@ -16,6 +16,7 @@ static const size_t VPN_MTU = 1460; // TODO determine this -- issue #3
UdpVpn::UdpVpn() UdpVpn::UdpVpn()
: _stopped(false), _vpn_mtu(VPN_MTU), _tun_dev("cvpn%d"), _peer(nullptr) : _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); _socket = socket(AF_INET6, SOCK_DGRAM, 0);
if(_socket < 0) if(_socket < 0)
throw UdpVpn::InitializationError("Cannot create socket", errno, true); throw UdpVpn::InitializationError("Cannot create socket", errno, true);

View file

@ -30,6 +30,10 @@ VpnPacketTLV VpnPacket::first_tlv() {
return VpnPacketTLV(*this, 0); 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 { uint32_t VpnPacket::get_seqno() const {
return *(uint32_t*)(_data + DATA_SEQNO_POS); return *(uint32_t*)(_data + DATA_SEQNO_POS);
} }

View file

@ -56,6 +56,9 @@ class VpnPacket {
VpnPacketTLV first_tlv(); 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 /// Set packet peer -- used for sequence numbers
void set_peer(VpnPeer* peer) { _peer = peer; } void set_peer(VpnPeer* peer) { _peer = peer; }