From caa8320743f9d7a051b54c9b7a01b1a8cd402c85 Mon Sep 17 00:00:00 2001 From: wangyu- Date: Fri, 27 Oct 2017 00:03:35 -0500 Subject: [PATCH] implement dev tun --- common.cpp | 63 ++++++++++++- common.h | 6 +- main.cpp | 7 +- misc.cpp | 39 ++++++-- misc.h | 2 +- tun_dev.cpp | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++- tun_dev.h | 7 +- tunnel.cpp | 61 +----------- 8 files changed, 374 insertions(+), 76 deletions(-) diff --git a/common.cpp b/common.cpp index d107829..a30823d 100644 --- a/common.cpp +++ b/common.cpp @@ -22,7 +22,9 @@ char iptables_rule[200]=""; program_mode_t client_or_server=unset_mode;//0 unset; 1client 2server -working_mode_t working_mode=unset_working_mode; +working_mode_t working_mode=tunnel_mode; + +int socket_buf_size=1024*1024; struct random_fd_t { @@ -526,3 +528,62 @@ int create_fifo(char * file) return fifo_fd; } + +int new_listen_socket(int &fd,u32_t ip,int port) +{ + fd =socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + int yes = 1; + //setsockopt(udp_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + + struct sockaddr_in local_me={0}; + + socklen_t slen = sizeof(sockaddr_in); + //memset(&local_me, 0, sizeof(local_me)); + local_me.sin_family = AF_INET; + local_me.sin_port = htons(port); + local_me.sin_addr.s_addr = ip; + + if (bind(fd, (struct sockaddr*) &local_me, slen) == -1) { + mylog(log_fatal,"socket bind error\n"); + //perror("socket bind error"); + myexit(1); + } + setnonblocking(fd); + set_buf_size(fd,socket_buf_size); + + mylog(log_debug,"local_listen_fd=%d\n,",fd); + + return 0; +} +int new_connected_socket(int &fd,u32_t ip,int port) +{ + char ip_port[40]; + sprintf(ip_port,"%s:%d",my_ntoa(ip),port); + + struct sockaddr_in remote_addr_in = { 0 }; + + socklen_t slen = sizeof(sockaddr_in); + //memset(&remote_addr_in, 0, sizeof(remote_addr_in)); + remote_addr_in.sin_family = AF_INET; + remote_addr_in.sin_port = htons(port); + remote_addr_in.sin_addr.s_addr = ip; + + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + mylog(log_warn, "[%s]create udp_fd error\n", ip_port); + return -1; + } + setnonblocking(fd); + set_buf_size(fd, socket_buf_size); + + mylog(log_debug, "[%s]created new udp_fd %d\n", ip_port, fd); + int ret = connect(fd, (struct sockaddr *) &remote_addr_in, slen); + if (ret != 0) { + mylog(log_warn, "[%s]fd connect fail\n",ip_port); + close(fd); + return -1; + } + return 0; +} + diff --git a/common.h b/common.h index 3285153..cb6d40d 100644 --- a/common.h +++ b/common.h @@ -122,7 +122,7 @@ enum working_mode_t {unset_working_mode=0,tunnel_mode,tun_dev_mode}; extern working_mode_t working_mode; extern int delay_capacity; - +extern int socket_buf_size; typedef u32_t id_t; @@ -220,4 +220,8 @@ int create_fifo(char * file); int create_new_udp(int &new_udp_fd,int remote_address_uint32,int remote_port); */ +int new_listen_socket(int &fd,u32_t ip,int port); + +int new_connected_socket(int &fd,u32_t ip,int port); + #endif /* COMMON_H_ */ diff --git a/main.cpp b/main.cpp index 5e3ee7c..270dd4d 100644 --- a/main.cpp +++ b/main.cpp @@ -9,14 +9,13 @@ #include "fec_manager.h" #include "misc.h" #include "tunnel.h" +#include "tun_dev.h" using namespace std; int main(int argc, char *argv[]) { - working_mode=tunnel_mode; - - + //working_mode=tunnel_mode; assert(sizeof(u64_t)==8); assert(sizeof(i64_t)==8); @@ -47,9 +46,11 @@ int main(int argc, char *argv[]) { if(client_or_server==client_mode) { + tun_dev_client_event_loop(); } else { + tun_dev_server_event_loop(); } } diff --git a/misc.cpp b/misc.cpp index e373da3..103e384 100644 --- a/misc.cpp +++ b/misc.cpp @@ -38,7 +38,7 @@ fd_manager_t fd_manager; int time_mono_test=0; -int socket_buf_size=1024*1024; + int from_normal_to_fec(conn_info_t & conn_info,char *data,int len,int & out_n,char **&out_arr,int *&out_len,my_time_t *&out_delay) @@ -551,6 +551,7 @@ void process_arg(int argc, char *argv[]) {"fec", required_argument, 0,'f'}, {"jitter", required_argument, 0,'j'}, {"fifo", required_argument, 0, 1}, + {"tun-dev", optional_argument, 0, 1}, {NULL, 0, 0, 0} }; int option_index = 0; @@ -868,6 +869,12 @@ void process_arg(int argc, char *argv[]) mylog(log_info,"fifo_file =%s \n",fifo_file); } + else if(strcmp(long_options[option_index].name,"tun-dev")==0) + { + //sscanf(optarg,"%s",fifo_file); + mylog(log_info,"enabled tun-dev mode\n"); + working_mode=tun_dev_mode; + } else { mylog(log_fatal,"unknown option\n"); @@ -880,12 +887,6 @@ void process_arg(int argc, char *argv[]) } } - if (no_l) - mylog(log_fatal,"error: -i not found\n"); - if (no_r) - mylog(log_fatal,"error: -o not found\n"); - if (no_l || no_r) - myexit(-1); if (is_client == 0 && is_server == 0) { mylog(log_fatal,"-s -c hasnt been set\n"); @@ -905,6 +906,30 @@ void process_arg(int argc, char *argv[]) client_or_server=server_mode; } + + if(working_mode==tunnel_mode) + { + if (no_l) + mylog(log_fatal,"error: -l not found\n"); + if (no_r) + mylog(log_fatal,"error: -r not found\n"); + if (no_l || no_r) + myexit(-1); + } + else if(working_mode==tun_dev_mode) + { + if(client_or_server==client_mode&&no_r) + { + mylog(log_fatal,"error: -r not found\n"); + myexit(-1); + } + else if(client_or_server==server_mode&&no_l) + { + mylog(log_fatal,"error: -l not found\n"); + myexit(-1); + } + } + print_parameter(); } diff --git a/misc.h b/misc.h index 3058552..b701dc6 100644 --- a/misc.h +++ b/misc.h @@ -44,7 +44,7 @@ extern fd_manager_t fd_manager; extern int time_mono_test; -extern int socket_buf_size; + int from_normal_to_fec(conn_info_t & conn_info,char *data,int len,int & out_n,char **&out_arr,int *&out_len,my_time_t *&out_delay); diff --git a/tun_dev.cpp b/tun_dev.cpp index bb61a46..b12fdcf 100644 --- a/tun_dev.cpp +++ b/tun_dev.cpp @@ -8,7 +8,7 @@ #include "common.h" #include "log.h" - +#include "misc.h" int get_tun_fd(char * dev_name) { int tun_fd=open("/dev/net/tun",O_RDWR); @@ -32,3 +32,266 @@ int get_tun_fd(char * dev_name) return tun_fd; } +int set_if(char *if_name,char * local_ip,char * remote_ip,int mtu) +{ + //printf("i m here1\n"); + struct ifreq ifr; + struct sockaddr_in sai; + memset(&ifr,0,sizeof(ifr)); + memset(&sai, 0, sizeof(struct sockaddr)); + + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + strncpy(ifr.ifr_name, if_name, IFNAMSIZ); + + sai.sin_family = AF_INET; + sai.sin_port = 0; + sai.sin_addr.s_addr = inet_addr(local_ip); + memcpy(&ifr.ifr_addr,&sai, sizeof(struct sockaddr)); + assert(ioctl(sockfd, SIOCSIFADDR, &ifr)==0); + + + + sai.sin_addr.s_addr = inet_addr(local_ip); + memcpy(&ifr.ifr_addr,&sai, sizeof(struct sockaddr)); + assert(ioctl(sockfd, SIOCSIFADDR, &ifr)==0); + + + + sai.sin_addr.s_addr = inet_addr(remote_ip); + memcpy(&ifr.ifr_addr,&sai, sizeof(struct sockaddr)); + assert(ioctl(sockfd, SIOCSIFDSTADDR, &ifr)==0); + + ifr.ifr_mtu=mtu; + assert(ioctl(sockfd, SIOCSIFMTU, &ifr)==0); + + + assert(ioctl(sockfd, SIOCGIFFLAGS, &ifr)==0); + // ifr.ifr_flags |= ( IFF_UP|IFF_POINTOPOINT|IFF_RUNNING|IFF_NOARP|IFF_MULTICAST ); + ifr.ifr_flags |= ( IFF_UP|IFF_POINTOPOINT|IFF_RUNNING|IFF_NOARP|IFF_MULTICAST ); + assert(ioctl(sockfd, SIOCSIFFLAGS, &ifr)==0); + + //printf("i m here2\n"); + return 0; +} + + +int tun_dev_client_event_loop() +{ + char buf[buf_len+1]; + //char *data=buf+1; + int len; + int i,j,k,ret; + int epoll_fd,tun_fd; + + int remote_fd; + fd64_t remote_fd64; + + + tun_fd=get_tun_fd("tun11"); + assert(tun_fd>0); + + assert(new_connected_socket(remote_fd,remote_ip_uint32,remote_port)==0); + remote_fd64=fd_manager.create(remote_fd); + + assert(set_if("tun11","10.0.0.2","10.0.0.1",1000)==0); + + epoll_fd = epoll_create1(0); + assert(epoll_fd>0); + + const int max_events = 4096; + struct epoll_event ev, events[max_events]; + if (epoll_fd < 0) { + mylog(log_fatal,"epoll return %d\n", epoll_fd); + myexit(-1); + } + + ev.events = EPOLLIN; + ev.data.u64 = remote_fd64; + ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, remote_fd, &ev); + if (ret!=0) { + mylog(log_fatal,"add remote_fd64 error\n"); + myexit(-1); + } + + ev.events = EPOLLIN; + ev.data.u64 = tun_fd; + ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, tun_fd, &ev); + if (ret!=0) { + mylog(log_fatal,"add tun_fd error\n"); + myexit(-1); + } + + dest_t dest; + dest.type=type_fd64; + dest.inner.fd64=remote_fd64; + //dest.conv=conv; + //dest.inner.ip_port=dest_ip_port; + //dest.cook=1; + + while(1)//////////////////////// + { + + if(about_to_exit) myexit(0); + + int nfds = epoll_wait(epoll_fd, events, max_events, 180 * 1000); + if (nfds < 0) { //allow zero + if(errno==EINTR ) + { + mylog(log_info,"epoll interrupted by signal\n"); + myexit(0); + } + else + { + mylog(log_fatal,"epoll_wait return %d\n", nfds); + myexit(-1); + } + } + int idx; + for (idx = 0; idx < nfds; ++idx) + { + if(events[idx].data.u64==(u64_t)tun_fd) + { + len=read(tun_fd,buf,max_data_len); + assert(len>=0); + + mylog(log_trace,"Received packet from tun,len: %d\n",len); + + delay_manager.add(0,dest,buf,len);; + } + else if(events[idx].data.u64==(u64_t)remote_fd64) + { + fd64_t fd64=events[idx].data.u64; + int fd=fd_manager.to_fd(fd64); + + len=recv(fd,buf,max_data_len,0); + + mylog(log_trace,"Received packet from udp,len: %d\n",len); + assert(len>=0); + + assert(write(tun_fd,buf,len)>0); + } + } + delay_manager.check(); + } + + + return 0; +} + +int tun_dev_server_event_loop() +{ + char buf[buf_len+1]; + char *data=buf+1; + int len; + int i,j,k,ret; + int epoll_fd,tun_fd; + + tun_fd=get_tun_fd("tun11"); + assert(tun_fd>0); + + assert(new_listen_socket(local_listen_fd,local_ip_uint32,local_port)==0); + + assert(set_if("tun11","10.0.0.1","10.0.0.2",1000)==0); + + epoll_fd = epoll_create1(0); + assert(epoll_fd>0); + + const int max_events = 4096; + struct epoll_event ev, events[max_events]; + if (epoll_fd < 0) { + mylog(log_fatal,"epoll return %d\n", epoll_fd); + myexit(-1); + } + + ev.events = EPOLLIN; + ev.data.u64 = local_listen_fd; + ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, local_listen_fd, &ev); + if (ret!=0) { + mylog(log_fatal,"add udp_listen_fd error\n"); + myexit(-1); + } + + ev.events = EPOLLIN; + ev.data.u64 = tun_fd; + ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, tun_fd, &ev); + if (ret!=0) { + mylog(log_fatal,"add tun_fd error\n"); + myexit(-1); + } + + //ip_port_t dest_ip_port; + + dest_t dest; + dest.type=type_ip_port; + dest.inner.ip_port.ip=0; + dest.inner.ip_port.port=0; + //dest.conv=conv; + //dest.inner.ip_port=dest_ip_port; + //dest.cook=1; + + while(1)//////////////////////// + { + + if(about_to_exit) myexit(0); + + int nfds = epoll_wait(epoll_fd, events, max_events, 180 * 1000); + if (nfds < 0) { //allow zero + if(errno==EINTR ) + { + mylog(log_info,"epoll interrupted by signal\n"); + myexit(0); + } + else + { + mylog(log_fatal,"epoll_wait return %d\n", nfds); + myexit(-1); + } + } + int idx; + for (idx = 0; idx < nfds; ++idx) + { + + if(events[idx].data.u64==(u64_t)local_listen_fd) + { + struct sockaddr_in udp_new_addr_in={0}; + socklen_t udp_new_addr_len = sizeof(sockaddr_in); + if ((len = recvfrom(local_listen_fd, buf, max_data_len, 0, + (struct sockaddr *) &udp_new_addr_in, &udp_new_addr_len)) == -1) { + mylog(log_error,"recv_from error,this shouldnt happen,err=%s,but we can try to continue\n",strerror(errno)); + continue; + //myexit(1); + }; + + dest.inner.ip_port.ip=udp_new_addr_in.sin_addr.s_addr; + dest.inner.ip_port.port=ntohs(udp_new_addr_in.sin_port); + + mylog(log_trace,"Received packet from %s:%d,len: %d\n", inet_ntoa(udp_new_addr_in.sin_addr), + ntohs(udp_new_addr_in.sin_port),len); + + assert(write(tun_fd,buf,len)>0); + + } + else if(events[idx].data.u64==(u64_t)tun_fd) + { + len=read(tun_fd,buf,max_data_len); + assert(len>=0); + + mylog(log_trace,"Received packet from tun,len: %d\n",len); + + if(dest.inner.ip_port.to_u64()==0) + { + mylog(log_warn,"there is no client yet\n"); + continue; + } + + delay_manager.add(0,dest,buf,len);; + + + } + } + delay_manager.check(); + } + + + return 0; +} diff --git a/tun_dev.h b/tun_dev.h index e9524a5..53454f9 100644 --- a/tun_dev.h +++ b/tun_dev.h @@ -5,11 +5,12 @@ * Author: root */ -#ifndef TUN_H_ -#define TUN_H_ - +#ifndef TUN_DEV_H_ +#define TUN_DEV_H_ +int tun_dev_client_event_loop(); +int tun_dev_server_event_loop(); #endif /* TUN_H_ */ diff --git a/tunnel.cpp b/tunnel.cpp index b8469c8..517d130 100644 --- a/tunnel.cpp +++ b/tunnel.cpp @@ -7,63 +7,6 @@ #include "tunnel.h" -int init_listen_socket() -{ - local_listen_fd =socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - - int yes = 1; - //setsockopt(udp_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - - struct sockaddr_in local_me={0}; - - socklen_t slen = sizeof(sockaddr_in); - //memset(&local_me, 0, sizeof(local_me)); - local_me.sin_family = AF_INET; - local_me.sin_port = htons(local_port); - local_me.sin_addr.s_addr = local_ip_uint32; - - if (bind(local_listen_fd, (struct sockaddr*) &local_me, slen) == -1) { - mylog(log_fatal,"socket bind error\n"); - //perror("socket bind error"); - myexit(1); - } - setnonblocking(local_listen_fd); - set_buf_size(local_listen_fd,socket_buf_size); - - mylog(log_debug,"local_listen_fd=%d\n,",local_listen_fd); - - return 0; -} -int new_connected_socket(int &fd,u32_t ip,int port) -{ - char ip_port[40]; - sprintf(ip_port,"%s:%d",my_ntoa(ip),port); - - struct sockaddr_in remote_addr_in = { 0 }; - - socklen_t slen = sizeof(sockaddr_in); - //memset(&remote_addr_in, 0, sizeof(remote_addr_in)); - remote_addr_in.sin_family = AF_INET; - remote_addr_in.sin_port = htons(port); - remote_addr_in.sin_addr.s_addr = ip; - - fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) { - mylog(log_warn, "[%s]create udp_fd error\n", ip_port); - return -1; - } - setnonblocking(fd); - set_buf_size(fd, socket_buf_size); - - mylog(log_debug, "[%s]created new udp_fd %d\n", ip_port, fd); - int ret = connect(fd, (struct sockaddr *) &remote_addr_in, slen); - if (ret != 0) { - mylog(log_warn, "[%s]fd connect fail\n",ip_port); - close(fd); - return -1; - } - return 0; -} int tunnel_client_event_loop() { @@ -79,7 +22,7 @@ int tunnel_client_event_loop() //conn_info.conv_manager.reserve(); //conn_info.fec_encode_manager.re_init(fec_data_num,fec_redundant_num,fec_mtu,fec_pending_num,fec_pending_time,fec_type); - init_listen_socket(); + new_listen_socket(local_listen_fd,local_ip_uint32,local_port); epoll_fd = epoll_create1(0); assert(epoll_fd>0); @@ -402,7 +345,7 @@ int tunnel_server_event_loop() // conn_info_t conn_info; - init_listen_socket(); + new_listen_socket(local_listen_fd,local_ip_uint32,local_port); epoll_fd = epoll_create1(0); assert(epoll_fd>0);