146 lines
3.2 KiB
C++
146 lines
3.2 KiB
C++
|
|
#include <stdio.h>
|
||
|
|
#include <fcntl.h>
|
||
|
|
#include <errno.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
#include <net/if.h>
|
||
|
|
#include <sys/ioctl.h>
|
||
|
|
#include <linux/if_tun.h>
|
||
|
|
|
||
|
|
#include "tfe_utils.h"
|
||
|
|
|
||
|
|
#ifndef TUN_PATH
|
||
|
|
#define TUN_PATH "/dev/net/tun"
|
||
|
|
#endif
|
||
|
|
|
||
|
|
extern void *g_default_logger;
|
||
|
|
|
||
|
|
/*
|
||
|
|
* IFF_TUN : TUN device (IP)
|
||
|
|
* IFF_TAP : TAP device (Ethernet)
|
||
|
|
* IFF_NO_PI : Do not provide packet information
|
||
|
|
* IFF_MULTI_QUEUE : Create a queue of multiqueue device
|
||
|
|
* IFF_ONE_QUEUE : Create a queue of oniequeue device
|
||
|
|
*/
|
||
|
|
int tap_open(const char *eth, int flags)
|
||
|
|
{
|
||
|
|
int sockfd = open(TUN_PATH, O_RDWR);
|
||
|
|
if (sockfd == -1)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to open " TUN_PATH ", %s.\n", strerror(errno));
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct ifreq ifr;
|
||
|
|
memset(&ifr, 0, sizeof(ifr));
|
||
|
|
ifr.ifr_flags = flags;
|
||
|
|
strcpy(ifr.ifr_name, eth);
|
||
|
|
if (ioctl(sockfd, TUNSETIFF, &ifr) == -1)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to attach %s, %s.\n", eth, strerror(errno));
|
||
|
|
goto error;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* The TUNSETPERSIST ioctl can be used to make the TUN/TAP interface persistent.
|
||
|
|
* In this mode, the interface won't be destroyed when the last process closes the associated /dev/net/tun file descriptor.
|
||
|
|
*/
|
||
|
|
if (ioctl(sockfd, TUNSETPERSIST, 1) == -1)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to set persist on %s, %s.\n", eth, strerror(errno));
|
||
|
|
goto error;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ioctl(sockfd, TUNSETOWNER, 0) == -1)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to set owner on %s, %s.\n", eth, strerror(errno));
|
||
|
|
goto error;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ioctl(sockfd, TUNSETGROUP, 0) == -1)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to set group on %s, %s.\n", eth, strerror(errno));
|
||
|
|
goto error;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK) == -1)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to set nonblock on fd: %d, %s.\n", sockfd, strerror(errno));
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return sockfd;
|
||
|
|
|
||
|
|
error:
|
||
|
|
if (sockfd > 0)
|
||
|
|
{
|
||
|
|
close(sockfd);
|
||
|
|
}
|
||
|
|
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void tap_close(int sockfd)
|
||
|
|
{
|
||
|
|
if (sockfd > 0)
|
||
|
|
{
|
||
|
|
close(sockfd);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int tap_up_link(const char *eth)
|
||
|
|
{
|
||
|
|
int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
|
||
|
|
if (sockfd == -1)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to create socket, %s.\n", strerror(errno));
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct ifreq ifr;
|
||
|
|
memset(&ifr, 0, sizeof(ifr));
|
||
|
|
strcpy(ifr.ifr_name, eth);
|
||
|
|
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) == -1)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to get link status on %s, %s.\n", eth, strerror(errno));
|
||
|
|
close(sockfd);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((ifr.ifr_flags & IFF_UP) == 0)
|
||
|
|
{
|
||
|
|
ifr.ifr_flags |= IFF_UP;
|
||
|
|
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to set link up on %s, %s.\n", eth, strerror(errno));
|
||
|
|
close(sockfd);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
close(sockfd);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int tap_get_mtu(const char *eth)
|
||
|
|
{
|
||
|
|
int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
|
||
|
|
if (sockfd == -1)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to create socket, %s.\n", strerror(errno));
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct ifreq ifr;
|
||
|
|
memset(&ifr, 0, sizeof(ifr));
|
||
|
|
strcpy(ifr.ifr_name, eth);
|
||
|
|
if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0)
|
||
|
|
{
|
||
|
|
TFE_LOG_ERROR(g_default_logger, "unable to get mtu on %s, %s.\n", eth, strerror(errno));
|
||
|
|
close(sockfd);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
close(sockfd);
|
||
|
|
return ifr.ifr_mtu;
|
||
|
|
}
|