This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
tango-kni/entry/src/kni_tun.cpp

91 lines
2.7 KiB
C++
Raw Normal View History

2019-09-06 16:50:37 +08:00
#include "kni_utils.h"
#include <sys/ioctl.h>
#include <fcntl.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <kni_tun.h>
struct kni_tun_handle{
int fd;
void *logger;
enum kni_tun_mode mode;
};
void kni_tun_destroy(struct kni_tun_handle *tun_handle){
if(tun_handle != NULL){
close(tun_handle->fd);
FREE(&tun_handle);
}
}
struct kni_tun_handle* kni_tun_init(char *tun_name, enum kni_tun_mode mode, void *logger){
struct kni_tun_handle *tun_handle = ALLOC(struct kni_tun_handle, 1);
tun_handle->logger = logger;
char *tun_path = (char*)"/dev/net/tun";
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int fd = -1, ret;
ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE;
if(tun_name == NULL || *tun_name == '\0'){
KNI_LOG_ERROR(logger, "Tap device name is NULL");
goto error_out;
}
strncpy(ifr.ifr_name, tun_name, IFNAMSIZ);
fd = open(tun_path, O_RDWR);
if(fd < 0){
KNI_LOG_ERROR(logger, "Failed at open file, filename = %s, errno = %d(%s)", tun_path, errno, strerror(errno));
goto error_out;
}
tun_handle->fd = fd;
tun_handle->mode = KNI_TUN_MODE_NOBLOCK;
if(tun_handle->mode == KNI_TUN_MODE_NOBLOCK){
int flags = fcntl(fd, F_GETFL, 0);
ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
if(ret < 0){
KNI_LOG_ERROR(logger ,"Failed at fcntl, fd = %d, flags = F_GETFL | O_NONBLOCK, errno = %d(%s)", errno, strerror(errno));
goto error_out;
}
}
ret = ioctl(tun_handle->fd, TUNSETIFF, (void *)&ifr);
if(ret < 0){
KNI_LOG_ERROR(logger ,"Failed at ioctl, fd = %d, errno = %d(%s)", errno, strerror(errno));
goto error_out;
}
return tun_handle;
error_out:
kni_tun_destroy(tun_handle);
return NULL;
}
int kni_tun_write(struct kni_tun_handle *handle, char *buff, uint16_t buff_len){
uint16_t ret = write(handle->fd, buff, buff_len);
if(ret < 0){
KNI_LOG_ERROR(handle->logger, "Failed at write, errno = %d(%s)", errno, strerror(errno));
return -1;
}
if(ret < buff_len){
KNI_LOG_ERROR(handle->logger, "Failed at write: need send %dB, only send %dB", buff_len, ret);
return -1;
}
return 0;
}
/*
* >= 0 : read data length
* = -1 : error
*/
int kni_tun_read(struct kni_tun_handle *handle, char *buff, uint16_t buff_len){
int ret = 0;
ret = read(handle->fd, buff, buff_len);
if(ret < 0){
if(ret == -1 && handle->mode == KNI_TUN_MODE_NOBLOCK){
if(errno == EWOULDBLOCK || errno == EAGAIN){
return 0;
}
}
2019-12-05 16:46:33 +08:00
KNI_LOG_ERROR(handle->logger, "Failed at read, error = %d(%s)", errno, strerror(errno));
2019-09-06 16:50:37 +08:00
}
return ret;
}