Setup tun device

This commit is contained in:
Théophile Bastian 2020-06-02 13:08:23 +02:00
parent 5c4b52acc6
commit 1f96a34a37
7 changed files with 138 additions and 0 deletions

2
.gitignore vendored
View file

@ -88,3 +88,5 @@ docs/_build/
# PyBuilder
target/
# ---> Local ignores
congestvpn

19
Makefile Normal file
View file

@ -0,0 +1,19 @@
CXX=g++
CXXFLAGS=-O2 -g -Wall -Wextra -std=c++17
CXXLIBS=
OBJS=TunDevice.o util.o main.o
TARGET=congestvpn
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) $(CXXLIBS) -o $@ $^
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
clean:
rm -f $(OBJS) $(TARGET)
.PHONY: all clean

46
TunDevice.cpp Normal file
View file

@ -0,0 +1,46 @@
#include <linux/if.h>
#include <linux/if_tun.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdlib>
#include <cstring>
#include "TunDevice.hpp"
TunDevice::TunDevice(const std::string& dev)
{
struct ifreq ifr;
int fd, err;
if( (fd = open("/dev/net/tun", O_RDWR)) < 0 )
throw TunDevice::InitializationError("Cannot open /dev/net/tun", fd);
memset(&ifr, 0, sizeof(ifr));
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TUN;
if(!dev.empty()) {
if(dev.size() >= IFNAMSIZ - 2)
throw TunDevice::InitializationError("Device name is too long.");
strncpy(ifr.ifr_name, dev.c_str(), IFNAMSIZ-1);
}
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
close(fd);
throw TunDevice::InitializationError(
"Tunnel interface failed [TUNSETIFF]", err
);
}
_dev_name = ifr.ifr_name;
_fd = fd;
}
TunDevice::~TunDevice() {
close(_fd);
}

22
TunDevice.hpp Normal file
View file

@ -0,0 +1,22 @@
#pragma once
#include <string>
#include "util.hpp"
class TunDevice {
public:
class InitializationError : public MsgException {
public:
InitializationError(const std::string& msg, int code=0)
: MsgException(msg, code) {}
};
TunDevice(const std::string& dev);
~TunDevice();
const std::string& get_dev_name() const { return _dev_name; }
int get_fd() const { return _fd; }
private:
int _fd;
std::string _dev_name;
};

17
main.cpp Normal file
View file

@ -0,0 +1,17 @@
#include <cstdio>
#include <unistd.h>
#include "TunDevice.hpp"
int main(void) {
try {
TunDevice tun_dev("cvpn%d");
printf("Tunnel device opened: <%s>, fd <%d>.\nSleeping 10 seconds.\n",
tun_dev.get_dev_name().c_str(), tun_dev.get_fd());
sleep(10);
printf("Shutting down.\n");
} catch(const TunDevice::InitializationError& exn) {
fprintf(stderr, "ERROR: %s\n", exn.what());
}
return 0;
}

15
util.cpp Normal file
View file

@ -0,0 +1,15 @@
#include <cstdio>
#include "util.hpp"
MsgException::MsgException(const std::string& msg, int code)
: _msg(msg), _code(code)
{
_what = _msg;
if(_code != 0) {
char remainder[20];
sprintf(remainder, " (code %d)", _code);
_what += remainder;
}
}

17
util.hpp Normal file
View file

@ -0,0 +1,17 @@
#pragma once
#include <exception>
#include <string>
// MsgException -- an exception bearing a passed explanation message
class MsgException : public std::exception {
public:
MsgException(const std::string& msg, int code=0);
int errcode() const noexcept { return _code; }
const char* what() const noexcept { return _what.c_str(); };
private:
std::string _msg;
int _code;
std::string _what;
};