支持tun模式调通
This commit is contained in:
91
entry/src/kni_tun.cpp
Normal file
91
entry/src/kni_tun.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
KNI_LOG_ERROR(handle -> logger, "Failed at read, error = %d(%s)", errno, strerror(errno));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user