From 5a51248cb053e13aae562a94e21f6086c3c2162e Mon Sep 17 00:00:00 2001 From: wangyu Date: Wed, 15 Jul 2020 15:29:32 -0400 Subject: [PATCH] unify udpraw linux and mp branch --- client.cpp | 269 ++++++++++++++++++++++- common.cpp | 136 ++++++++++++ common.h | 56 ++++- main.cpp | 18 ++ misc.cpp | 191 +++++++++++++++- network.cpp | 610 +++++++++++++++++++++++++++++++++++++++++++++++++++- network.h | 34 +++ server.cpp | 3 + 8 files changed, 1310 insertions(+), 7 deletions(-) diff --git a/client.cpp b/client.cpp index 29375f8..d9cba58 100644 --- a/client.cpp +++ b/client.cpp @@ -7,6 +7,18 @@ #include "encrypt.h" #include "fd_manager.h" +#ifdef UDP2RAW_MP +u32_t detect_interval=1500; +u64_t laste_detect_time=0; + +int use_udp_for_detection=0; +int use_tcp_for_detection=1; + + +extern pcap_t *pcap_handle; + +extern int pcap_captured_full_len; +#endif int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is ready in epoll { @@ -20,6 +32,75 @@ int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is mylog(log_trace,"\n",send_info.ts_ack); +#ifdef UDP2RAW_MP + //mylog(log_debug,"pcap cnt :%d\n",pcap_cnt); + if(send_with_pcap&&!pcap_header_captured) + { + + if(get_current_time()-laste_detect_time>detect_interval) + { + laste_detect_time=get_current_time(); + } + else + { + return 0; + } +/* + struct sockaddr_in remote_addr_in={0}; + + socklen_t slen = sizeof(sockaddr_in); + int port=get_true_random_number()%65534+1; + remote_addr_in.sin_family = AF_INET; + remote_addr_in.sin_port = htons(port); + remote_addr_in.sin_addr.s_addr = remote_ip_uint32;*/ + int port=get_true_random_number()%65534+1; + address_t tmp_addr=remote_addr; + tmp_addr.set_port(port); + + if(use_udp_for_detection) + { + int new_udp_fd=socket(tmp_addr.get_type(), SOCK_DGRAM, IPPROTO_UDP); + if(new_udp_fd<0) + { + mylog(log_warn,"create new_udp_fd error\n"); + return -1; + } + setnonblocking(new_udp_fd); + u64_t tmp=get_true_random_number(); + + int ret=sendto(new_udp_fd,(char*)(&tmp),sizeof(tmp),0,(struct sockaddr *)&tmp_addr.inner,tmp_addr.get_len()); + if(ret==-1) + { + mylog(log_warn,"sendto() failed\n"); + } + sock_close(new_udp_fd); + } + + if(use_tcp_for_detection) + { + static int last_tcp_fd=-1; + + int new_tcp_fd=socket(tmp_addr.get_type(), SOCK_STREAM, IPPROTO_TCP); + if(new_tcp_fd<0) + { + mylog(log_warn,"create new_tcp_fd error\n"); + return -1; + } + setnonblocking(new_tcp_fd); + connect(new_tcp_fd,(struct sockaddr *)&tmp_addr.inner,tmp_addr.get_len()); + if(last_tcp_fd!=-1) + sock_close(last_tcp_fd); + last_tcp_fd=new_tcp_fd; + //close(new_tcp_fd); + } + + + + mylog(log_info,"waiting for a use-able packet to be captured\n"); + + return 0; + } +#endif if(raw_info.disabled) { conn_info.state.client_current_state=client_idle; @@ -387,7 +468,10 @@ int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a p raw_info_t &raw_info=conn_info.raw_info; mylog(log_trace,"\n",send_info.ts_ack); + +#ifdef UDP2RAW_LINUX if(pre_recv_raw_packet()<0) return -1; +#endif if(conn_info.state.client_current_state==client_idle ) { @@ -583,10 +667,71 @@ void udp_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) } void raw_recv_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) { - //assert(0==1); + if(is_udp2raw_mp)assert(0==1); conn_info_t & conn_info= *((conn_info_t*)watcher->data); client_on_raw_recv(conn_info); } +#ifdef UDP2RAW_MP +void async_cb(struct ev_loop *loop, struct ev_async *watcher, int revents) +{ + conn_info_t & conn_info= *((conn_info_t*)watcher->data); + + if(send_with_pcap&&!pcap_header_captured) + { + int empty=0;char *p;int len; + pthread_mutex_lock(&queue_mutex); + empty=my_queue.empty(); + if(!empty) + { + my_queue.peek_front(p,len); + my_queue.pop_front(); + } + pthread_mutex_unlock(&queue_mutex); + if(empty) return; + + pcap_header_captured=1; + assert(pcap_link_header_len!=-1); + memcpy(pcap_header_buf,p,max_data_len); + + log_bare(log_info,"link level header captured:\n"); + unsigned char *tmp=(unsigned char*)pcap_header_buf; + pcap_captured_full_len=len; + for(int i=0;i",(u32_t)tmp[i]); + + log_bare(log_info,"\n"); + return ; + } + + //mylog(log_info,"async_cb called\n"); + while(1) + { + int empty=0;char *p;int len; + pthread_mutex_lock(&queue_mutex); + empty=my_queue.empty(); + if(!empty) + { + my_queue.peek_front(p,len); + my_queue.pop_front(); + } + pthread_mutex_unlock(&queue_mutex); + + if(empty) break; + if(g_fix_gro==0&&len>max_data_len) + { + mylog(log_warn,"huge packet %d > %d, dropped\n",len,max_data_len); + break; + } + + int new_len=len-pcap_link_header_len; + memcpy(g_packet_buf,p+pcap_link_header_len,new_len); + g_packet_buf_len=new_len; + assert(g_packet_buf_cnt==0); + g_packet_buf_cnt++; + client_on_raw_recv(conn_info); + } +} +#endif void clear_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) { conn_info_t & conn_info= *((conn_info_t*)watcher->data); @@ -632,6 +777,7 @@ int client_event_loop() packet_info_t &send_info=conn_info.raw_info.send_info; packet_info_t &recv_info=conn_info.raw_info.recv_info; +#ifdef UDP2RAW_LINUX if(lower_level) { if(lower_level_manual) @@ -707,6 +853,116 @@ int client_event_loop() } } +#endif + +#ifdef UDP2RAW_MP + + address_t tmp_addr; + if(get_src_adress2(tmp_addr,remote_addr)!=0) + { + mylog(log_error,"get_src_adress() failed\n"); + myexit(-1); + } + if(strcmp(dev,"")==0) + { + mylog(log_info,"--dev have not been set, trying to detect automatically, avaliable deives:\n"); + + mylog(log_info,"avaliable deives(device name: ip address ; description):\n"); + + char errbuf[PCAP_ERRBUF_SIZE]; + + int found=0; + + pcap_if_t *interfaces,*d; + if(pcap_findalldevs(&interfaces,errbuf)==-1) + { + mylog(log_fatal,"error in pcap_findalldevs(),%s\n",errbuf); + myexit(-1); + } + + for(pcap_if_t *d=interfaces; d!=NULL; d=d->next) { + log_bare(log_warn,"%s:", d->name); + int cnt=0; + for(pcap_addr_t *a=d->addresses; a!=NULL; a=a->next) { + if(a->addr==NULL) + { + log_bare(log_debug," [a->addr==NULL]"); + continue; + } + if(a->addr->sa_family == AF_INET||a->addr->sa_family == AF_INET6) + { + cnt++; + + if(a->addr->sa_family ==AF_INET) + { + char s[max_addr_len]; + inet_ntop(AF_INET, &((struct sockaddr_in*)a->addr)->sin_addr, s,max_addr_len); + log_bare(log_warn," [%s]", s); + + if(a->addr->sa_family==raw_ip_version) + { + if(((struct sockaddr_in*)a->addr)->sin_addr.s_addr ==tmp_addr.inner.ipv4.sin_addr.s_addr) + { + found++; + strcpy(dev,d->name); + } + } + } + else + { + assert(a->addr->sa_family ==AF_INET6); + + char s[max_addr_len]; + inet_ntop(AF_INET6, &((struct sockaddr_in6*)a->addr)->sin6_addr, s,max_addr_len); + log_bare(log_warn," [%s]", s); + + if(a->addr->sa_family==raw_ip_version) + { + if( memcmp( &((struct sockaddr_in6*)a->addr)->sin6_addr,&tmp_addr.inner.ipv6.sin6_addr,sizeof(struct in6_addr))==0 ) + { + found++; + strcpy(dev,d->name); + } + } + } + } + else + { + log_bare(log_debug," [unknow:%d]",int(a->addr->sa_family)); + } + } + if(cnt==0) log_bare(log_warn," [no ip found]"); + if(d->description==0) + { + log_bare(log_warn,"; (no description avaliable)"); + } + else + { + log_bare(log_warn,"; %s", d->description); + } + log_bare(log_warn,"\n"); + } + + if(found==0) + { + mylog(log_fatal,"no matched device found for ip: [%s]\n",tmp_addr.get_ip()); + myexit(-1); + } + else if(found==1) + { + mylog(log_info,"using device:[%s], ip: [%s]\n",dev,tmp_addr.get_ip()); + } + else + { + mylog(log_fatal,"more than one devices found for ip: [%s] , you need to use --dev manually\n",tmp_addr.get_ip()); + myexit(-1); + } + } + else + { + mylog(log_info,"--dev has been manually set, using device:[%s]\n",dev); + } +#endif send_info.src_port=0; memset(&send_info.new_src_ip,0,sizeof(send_info.new_src_ip)); @@ -766,11 +1022,22 @@ int client_event_loop() // myexit(-1); //} +#ifdef UDP2RAW_LINUX struct ev_io raw_recv_watcher; raw_recv_watcher.data=&conn_info; ev_io_init(&raw_recv_watcher, raw_recv_cb, raw_recv_fd, EV_READ); ev_io_start(loop, &raw_recv_watcher); +#endif + +#ifdef UDP2RAW_MP + g_default_loop=loop; + async_watcher.data=&conn_info; + ev_async_init(&async_watcher,async_cb); + ev_async_start(loop,&async_watcher); + + init_raw_socket();//must be put after dev detection +#endif //set_timer(epollfd,timer_fd); struct ev_timer clear_timer; diff --git a/common.cpp b/common.cpp index dbb3596..6669537 100644 --- a/common.cpp +++ b/common.cpp @@ -345,6 +345,57 @@ int my_ip_t::from_str(char * str) } return 0; }*/ +#ifdef UDP2RAW_MP + +int init_ws() +{ +#if defined(__MINGW32__) + WORD wVersionRequested; + WSADATA wsaData; + int err; + + /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + /* Tell the user that we could not find a usable */ + /* Winsock DLL. */ + printf("WSAStartup failed with error: %d\n", err); + exit(-1); + } + + /* Confirm that the WinSock DLL supports 2.2.*/ + /* Note that if the DLL supports versions greater */ + /* than 2.2 in addition to 2.2, it will still return */ + /* 2.2 in wVersion since that is the version we */ + /* requested. */ + + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { + /* Tell the user that we could not find a usable */ + /* WinSock DLL. */ + printf("Could not find a usable version of Winsock.dll\n"); + WSACleanup(); + exit(-1); + } + else + { + printf("The Winsock 2.2 dll was found okay"); + } + + int tmp[]={0,100,200,300,500,800,1000,2000,3000,4000,-1}; + int succ=0; + for(int i=1;tmp[i]!=-1;i++) + { + if(_setmaxstdio(100)==-1) break; + else succ=i; + } + printf(", _setmaxstdio() was set to %d\n",tmp[succ]); +#endif +return 0; +} + +#endif #if defined(__MINGW32__) int inet_pton(int af, const char *src, void *dst) @@ -492,6 +543,8 @@ void init_random_number_fd() } setnonblocking(random_number_fd); }*/ + +#if !defined(__MINGW32__) struct random_fd_t { int random_number_fd; @@ -511,8 +564,60 @@ struct random_fd_t return random_number_fd; } }random_fd; +#else +struct my_random_t +{ + std::random_device rd; + std::mt19937 gen; + std::uniform_int_distribution dis64; + std::uniform_int_distribution dis32; + + std::uniform_int_distribution dis8; + + my_random_t() + { + //std::mt19937 gen_tmp(rd()); //random device is broken on mingw + timespec tmp_time; + clock_gettime(CLOCK_MONOTONIC, &tmp_time); + long long a=((u64_t)tmp_time.tv_sec)*1000000000llu+((u64_t)tmp_time.tv_nsec); + std::mt19937 gen_tmp(a); + gen=gen_tmp; + gen.discard(700000); //magic + } + u64_t gen64() + { + return dis64(gen); + } + u32_t gen32() + { + return dis32(gen); + } + + unsigned char gen8() + { + return dis8(gen); + } + /*int random_number_fd; + random_fd_t() + { + random_number_fd=open("/dev/urandom",O_RDONLY); + if(random_number_fd==-1) + { + mylog(log_fatal,"error open /dev/urandom\n"); + myexit(-1); + } + setnonblocking(random_number_fd); + } + int get_fd() + { + return random_number_fd; + }*/ +}my_random; +#endif + u64_t get_true_random_number_64() { +#if !defined(__MINGW32__) u64_t ret; int size=read(random_fd.get_fd(),&ret,sizeof(ret)); if(size!=sizeof(ret)) @@ -521,9 +626,13 @@ u64_t get_true_random_number_64() myexit(-1); } return ret; +#else + return my_random.gen64(); //fake random number +#endif } u32_t get_true_random_number() { +#if !defined(__MINGW32__) u32_t ret; int size=read(random_fd.get_fd(),&ret,sizeof(ret)); if(size!=sizeof(ret)) @@ -532,6 +641,9 @@ u32_t get_true_random_number() myexit(-1); } return ret; +#else + return my_random.gen32(); //fake random number +#endif } u32_t get_true_random_number_nz() //nz for non-zero { @@ -694,6 +806,13 @@ int set_buf_size(int fd,int socket_buf_size) { if(force_socket_buf) { + if(is_udp2raw_mp) + { + mylog(log_fatal,"force_socket_buf not supported in this verion\n"); + myexit(-1); + } + //assert(0==1); +#ifdef UDP2RAW_LINUX if(setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &socket_buf_size, sizeof(socket_buf_size))<0) { mylog(log_fatal,"SO_SNDBUFFORCE fail socket_buf_size=%d errno=%s\n",socket_buf_size,strerror(errno)); @@ -704,6 +823,8 @@ int set_buf_size(int fd,int socket_buf_size) mylog(log_fatal,"SO_RCVBUFFORCE fail socket_buf_size=%d errno=%s\n",socket_buf_size,strerror(errno)); myexit(1); } +#endif + } else { @@ -846,6 +967,7 @@ void myexit(int a) { if(enable_log_color) printf("%s\n",RESET); +#ifdef UDP2RAW_LINUX if(keep_thread_running) { if(pthread_cancel(keep_thread)) @@ -858,6 +980,7 @@ void myexit(int a) } } clear_iptables_rule(); +#endif exit(a); } @@ -927,6 +1050,12 @@ int read_file(const char * file,string &output) return 0; } int run_command(string command0,char * &output,int flag) { +if(is_udp2raw_mp) +{ + mylog(log_fatal,"run_command not supported in this version\n"); + myexit(-1); +} +#ifdef UDP2RAW_LINUX FILE *in; @@ -980,6 +1109,7 @@ int run_command(string command0,char * &output,int flag) { return -4; } +#endif return 0; } @@ -1100,6 +1230,7 @@ vector parse_conf_line(const string& s0) int create_fifo(char * file) { +#ifdef UDP2RAW_LINUX if(mkfifo (file, 0666)!=0) { if(errno==EEXIST) @@ -1133,6 +1264,11 @@ int create_fifo(char * file) setnonblocking(fifo_fd); return fifo_fd; +#else + mylog(log_fatal,"--fifo not supported in this version\n"); + myexit(-1); + return 0; +#endif } /* diff --git a/common.h b/common.h index 7379098..868cfb0 100644 --- a/common.h +++ b/common.h @@ -28,7 +28,7 @@ #include #if defined(UDP2RAW_MP) - +const int is_udp2raw_mp=1; #if !defined(__CYGWIN__) && !defined(__MINGW32__) #include #else @@ -40,8 +40,10 @@ #include #endif -#else +#else +#define UDP2RAW_LINUX +const int is_udp2raw_mp=0; //#include #include #include @@ -53,7 +55,11 @@ #endif +#if !defined(NO_LIBEV_EMBED) #include +#else +#include "ev.h" +#endif #if defined(__MINGW32__) #include @@ -355,6 +361,52 @@ const int buf_len=max_data_len+400; //const int max_address_len=512; +#ifdef UDP2RAW_MP +const int queue_len=200; + +struct queue_t +{ + char data[queue_len][huge_buf_len]; + int data_len[queue_len]; + + int head=0; + int tail=0; + void clear() + { + head=tail=0; + } + int empty() + { + if(head==tail) return 1; + else return 0; + } + int full() + { + if( (tail+1)%queue_len==head ) return 1; + else return 0; + } + void peek_front(char * & p,int &len) + { + assert(!empty()); + p=data[head]; + len=data_len[head]; + } + void pop_front() + { + assert(!empty()); + head++;head%=queue_len; + } + void push_back(char * p,int len) + { + assert(!full()); + memcpy(data[tail],p,len); + data_len[tail]=len; + tail++;tail%=queue_len; + } +}; + +int init_ws(); +#endif u64_t get_current_time(); u64_t pack_u64(u32_t a,u32_t b); diff --git a/main.cpp b/main.cpp index 9403c41..62ec321 100755 --- a/main.cpp +++ b/main.cpp @@ -33,6 +33,10 @@ int main(int argc, char *argv[]) assert(sizeof(unsigned int)==4); assert(sizeof(unsigned long long)==8); +#ifdef UDP2RAW_MP + init_ws(); +#endif + dup2(1, 2);//redirect stderr to stdout #if defined(__MINGW32__) enable_log_color=0; @@ -59,11 +63,17 @@ int main(int argc, char *argv[]) } else { +#ifdef UDP2RAW_LINUX signal(SIGINT, signal_handler); signal(SIGHUP, signal_handler); signal(SIGKILL, signal_handler); signal(SIGTERM, signal_handler); signal(SIGQUIT, signal_handler); +#else + mylog(log_fatal,"server mode not supported in multi-platform version\n"); + myexit(-1); +#endif + } #if !defined(__MINGW32__) if(geteuid() != 0) @@ -87,7 +97,10 @@ int main(int argc, char *argv[]) my_init_keys(key_string,program_mode==client_mode?1:0); iptables_rule(); + +#ifdef UDP2RAW_LINUX init_raw_socket(); +#endif if(program_mode==client_mode) { @@ -95,7 +108,12 @@ int main(int argc, char *argv[]) } else { +#ifdef UDP2RAW_LINUX server_event_loop(); +#else + mylog(log_fatal,"server mode not supported in multi-platform version\n"); + myexit(-1); +#endif } return 0; diff --git a/misc.cpp b/misc.cpp index fcbbae0..db92536 100644 --- a/misc.cpp +++ b/misc.cpp @@ -47,8 +47,10 @@ my_id_t const_id=0;//an id used for connection recovery,its generated randomly,i int udp_fd=-1; //for client only. client use this fd to listen and handle udp connection int bind_fd=-1; //bind only,never send or recv. its just a dummy fd for bind,so that other program wont occupy the same port +#ifdef UDP2RAW_LINUX int epollfd=-1; //fd for epoll int timer_fd=-1; //the general timer fd for client and server.for server this is not the only timer find,every connection has a timer fd. +#endif int fail_time_counter=0;//determine if the max_fail_time is reached int epoll_trigger_counter=0;//for debug only int debug_flag=0;//for debug only @@ -70,12 +72,14 @@ char fifo_file[1000]=""; int clear_iptables=0; int wait_xtables_lock=0; +#ifdef UDP2RAW_LINUX string iptables_command0="iptables/ip6tables "; string iptables_command=""; string iptables_pattern=""; int iptables_rule_added=0; int iptables_rule_keeped=0; int iptables_rule_keep_index=0; +#endif program_mode_t program_mode=unset_mode;//0 unset; 1client 2server raw_mode_t raw_mode=mode_faketcp; @@ -94,6 +98,7 @@ int socket_buf_size=1024*1024; //char lower_level_arg[1000]; +#ifdef UDP2RAW_LINUX int process_lower_level_arg()//handle --lower-level option { lower_level=1; @@ -122,6 +127,7 @@ int process_lower_level_arg()//handle --lower-level option } return 0; } +#endif void print_help() { char git_version_buf[100]={0}; @@ -131,12 +137,18 @@ void print_help() printf("build date:%s %s\n",__DATE__,__TIME__); printf("repository: https://github.com/wangyu-/udp2raw-tunnel\n"); printf("\n"); +#ifdef UDP2RAW_MP +#ifdef NO_LIBNET + printf("libnet is disabled at compile time\n"); + printf("\n"); +#endif +#endif printf("usage:\n"); printf(" run as client : ./this_program -c -l local_listen_ip:local_port -r server_address:server_port [options]\n"); printf(" run as server : ./this_program -s -l server_listen_ip:server_port -r remote_address:remote_port [options]\n"); printf("\n"); printf("common options,these options must be same on both side:\n"); - printf(" --raw-mode avaliable values:faketcp(default),udp,icmp\n"); + printf(" --raw-mode avaliable values:faketcp(default),udp,icmp and easy-faketcp\n"); printf(" -k,--key password to gen symetric key,default:\"secret key\"\n"); printf(" --cipher-mode avaliable values:aes128cfb,aes128cbc(default),xor,none\n"); printf(" --auth-mode avaliable values:hmac_sha1,md5(default),crc32,simple,none\n"); @@ -166,7 +178,9 @@ void print_help() printf(" --disable-bpf disable the kernel space filter,most time its not necessary\n"); printf(" unless you suspect there is a bug\n"); // printf("\n"); +#ifdef UDP2RAW_LINUX printf(" --dev bind raw socket to a device, not necessary but improves performance\n"); +#endif printf(" --sock-buf buf size for socket,>=10 and <=10240,unit:kbyte,default:1024\n"); printf(" --force-sock-buf bypass system limitation while setting sock-buf\n"); printf(" --seq-mode seq increase mode for faketcp:\n"); @@ -299,6 +313,10 @@ void process_arg(int argc, char *argv[]) //process all options {"dev", required_argument, 0, 1}, {"dns-resolve", no_argument, 0, 1}, {"easy-tcp", no_argument, 0, 1}, +#ifdef UDP2RAW_MP + {"pcap-send", no_argument, 0, 1}, + {"no-pcap-mutex", no_argument, 0, 1}, +#endif {"fix-gro", no_argument, 0, 1}, {NULL, 0, 0, 0} }; @@ -468,6 +486,11 @@ void process_arg(int argc, char *argv[]) //process all options case 'h': break; case 'a': +if(is_udp2raw_mp) +{ + mylog(log_fatal,"-a not supported in this version, check -g or --raw-mode easyfaketcp\n"); + myexit(-1); +} auto_add_iptables_rule=1; break; case 'g': @@ -481,6 +504,12 @@ void process_arg(int argc, char *argv[]) //process all options mylog(log_debug,"option_index: %d\n",option_index); if(strcmp(long_options[option_index].name,"clear")==0) { +if(is_udp2raw_mp) +{ + mylog(log_fatal,"--clear not supported in this version\n"); + myexit(-1); +} + clear_iptables=1; } else if(strcmp(long_options[option_index].name,"source-ip")==0) @@ -590,20 +619,44 @@ void process_arg(int argc, char *argv[]) //process all options } else if(strcmp(long_options[option_index].name,"lower-level")==0) { +if(is_udp2raw_mp) +{ + mylog(log_fatal,"--lower-level not supported in this version\n"); + myexit(-1); +} + +#ifdef UDP2RAW_LINUX process_lower_level_arg(); +#endif + //process_lower_level_arg(); //lower_level=1; //strcpy(lower_level_arg,optarg); } else if(strcmp(long_options[option_index].name,"simple-rule")==0) { +if(is_udp2raw_mp) +{ + mylog(log_fatal,"--simple-rule not supported in this version\n"); + myexit(-1); +} simple_rule=1; } else if(strcmp(long_options[option_index].name,"keep-rule")==0) { +if(is_udp2raw_mp) +{ + mylog(log_fatal,"--keep-rule not supported in this version\n"); + myexit(-1); +} keep_rule=1; } else if(strcmp(long_options[option_index].name,"gen-add")==0) { +if(is_udp2raw_mp) +{ + mylog(log_fatal,"--gen-add not supported in this version\n"); + myexit(-1); +} generate_iptables_rule_add=1; } else if(strcmp(long_options[option_index].name,"disable-color")==0) @@ -636,6 +689,11 @@ void process_arg(int argc, char *argv[]) //process all options } else if(strcmp(long_options[option_index].name,"force-sock-buf")==0) { +if(is_udp2raw_mp) +{ + mylog(log_fatal,"--force-sock-buf not supported in this version\n"); + myexit(-1); +} force_socket_buf=1; } else if(strcmp(long_options[option_index].name,"retry-on-error")==0) @@ -692,6 +750,11 @@ void process_arg(int argc, char *argv[]) //process all options } else if(strcmp(long_options[option_index].name,"fifo")==0) { +if(is_udp2raw_mp) +{ + mylog(log_fatal,"--fifo not supported in this version\n"); + myexit(-1); +} sscanf(optarg,"%s",fifo_file); mylog(log_info,"fifo_file =%s \n",fifo_file); @@ -742,6 +805,18 @@ void process_arg(int argc, char *argv[]) //process all options enable_dns_resolve=1; mylog(log_info,"dns-resolve enabled\n"); } +#ifdef UDP2RAW_MP + else if(strcmp(long_options[option_index].name,"pcap-send")==0) + { + send_with_pcap=1; + mylog(log_info,"--pcap-send enabled, now pcap will be used for sending packet instead of libnet\n"); + } + else if(strcmp(long_options[option_index].name,"no-pcap-mutex")==0) + { + use_pcap_mutex=0; + mylog(log_warn,"--no-pcap-mutex enabled, we will assume the underlying pcap calls are threadsafe\n"); + } +#endif else if(strcmp(long_options[option_index].name,"easy-tcp")==0) { use_tcp_dummy_socket=1; @@ -904,6 +979,7 @@ void pre_process_arg(int argc, char *argv[])//mainly for load conf file process_arg(new_argc,new_argv_char); } +#ifdef UDP2RAW_LINUX void *run_keep(void *none) //called in a new thread for --keep-rule option { @@ -1092,6 +1168,7 @@ void iptables_rule() // handles -a -g --gen-add --keep-rule --clear --wait-loc mylog(log_warn," -a has not been set, make sure you have added the needed iptables rules manually\n"); } } +#endif int unit_test() { @@ -1151,6 +1228,7 @@ int unit_test() return 0; } +#ifdef UDP2RAW_LINUX int set_timer(int epollfd,int &timer_fd)//put a timer_fd into epoll,general function,used both in client and server { int ret; @@ -1379,6 +1457,117 @@ int clear_iptables_rule() } return 0; } +#endif + +#ifdef UDP2RAW_MP +void iptables_rule() // handles -a -g --gen-add --keep-rule --clear --wait-lock +{ + + if(generate_iptables_rule) + { + if(raw_mode==mode_faketcp && use_tcp_dummy_socket==1) + { + mylog(log_fatal, "failed,-g doesnt work with easy-faketcp mode\n"); + myexit(-1); + } + if(raw_mode==mode_udp) + { + mylog(log_warn, "It not necessary to use iptables/firewall rule in udp mode\n"); + } + log_bare(log_warn,"for linux, use:\n"); + if(raw_ip_version==AF_INET) + { + if(raw_mode==mode_faketcp) + printf("iptables -I INPUT -s %s -p tcp -m tcp --sport %d -j DROP\n",remote_addr.get_ip(),remote_addr.get_port()); + if(raw_mode==mode_udp) + printf("iptables -I INPUT -s %s -p udp -m udp --sport %d -j DROP\n",remote_addr.get_ip(),remote_addr.get_port()); + if(raw_mode==mode_icmp) + printf("iptables -I INPUT -s %s -p icmp --icmp-type 0 -j DROP\n",remote_addr.get_ip()); + printf("\n"); + } + else + { + assert(raw_ip_version==AF_INET6); + if(raw_mode==mode_faketcp) + printf("ip6tables -I INPUT -s %s -p tcp -m tcp --sport %d -j DROP\n",remote_addr.get_ip(),remote_addr.get_port()); + if(raw_mode==mode_udp) + printf("ip6tables -I INPUT -s %s -p udp -m udp --sport %d -j DROP\n",remote_addr.get_ip(),remote_addr.get_port()); + if(raw_mode==mode_icmp) + printf("ip6tables -I INPUT -s %s -p -p icmpv6 --icmpv6-type 129 -j DROP\n",remote_addr.get_ip()); + printf("\n"); + } + + log_bare(log_warn,"for mac/bsd use:\n"); + if(raw_ip_version==AF_INET) + { + if(raw_mode==mode_faketcp) + printf("echo 'block drop inet proto tcp from %s port %d to any' > ./1.conf\n",remote_addr.get_ip(),remote_addr.get_port()); + if(raw_mode==mode_udp) + printf("echo 'block drop inet proto udp from %s port %d to any' > ./1.conf\n",remote_addr.get_ip(),remote_addr.get_port()); + if(raw_mode==mode_icmp) + printf("echo 'block drop inet proto icmp from %s to any' > ./1.conf\n",remote_addr.get_ip()); + } + else + { + assert(raw_ip_version==AF_INET6); + if(raw_mode==mode_faketcp) + printf("echo 'block drop inet6 proto tcp from %s port %d to any' > ./1.conf\n",remote_addr.get_ip(),remote_addr.get_port()); + if(raw_mode==mode_udp) + printf("echo 'block drop inet6 proto udp from %s port %d to any' > ./1.conf\n",remote_addr.get_ip(),remote_addr.get_port()); + if(raw_mode==mode_icmp) + printf("echo 'block drop inet6 proto icmp6 from %s to any' > ./1.conf\n",remote_addr.get_ip()); + } + printf("pfctl -f ./1.conf\n"); + printf("pfctl -e\n"); + printf("\n"); + + log_bare(log_warn,"for windows vista and above use:\n"); + if(raw_ip_version==AF_INET) + { + if(raw_mode==mode_faketcp) + { + printf("netsh advfirewall firewall add rule name=udp2raw protocol=TCP dir=in remoteip=%s remoteport=%d action=block\n",remote_addr.get_ip(),remote_addr.get_port()); + printf("netsh advfirewall firewall add rule name=udp2raw protocol=TCP dir=out remoteip=%s remoteport=%d action=block\n",remote_addr.get_ip(),remote_addr.get_port()); + } + if(raw_mode==mode_udp) + { + printf("netsh advfirewall firewall add rule name=udp2raw protocol=UDP dir=in remoteip=%s remoteport=%d action=block\n",remote_addr.get_ip(),remote_addr.get_port()); + printf("netsh advfirewall firewall add rule name=udp2raw protocol=UDP dir=out remoteip=%s remoteport=%d action=block\n",remote_addr.get_ip(),remote_addr.get_port()); + } + + if(raw_mode==mode_icmp) + { + printf("netsh advfirewall firewall add rule name=udp2raw protocol=ICMPV4 dir=in remoteip=%s action=block\n",remote_addr.get_ip()); + printf("netsh advfirewall firewall add rule name=udp2raw protocol=ICMPV4 dir=out remoteip=%s action=block\n",remote_addr.get_ip()); + } + } + else + { + assert(raw_ip_version==AF_INET6); + if(raw_mode==mode_faketcp) + { + printf("netsh advfirewall firewall add rule name=udp2raw protocol=TCP dir=in remoteip=%s remoteport=%d action=block\n",remote_addr.get_ip(),remote_addr.get_port()); + printf("netsh advfirewall firewall add rule name=udp2raw protocol=TCP dir=out remoteip=%s remoteport=%d action=block\n",remote_addr.get_ip(),remote_addr.get_port()); + } + if(raw_mode==mode_udp) + { + printf("netsh advfirewall firewall add rule name=udp2raw protocol=UDP dir=in remoteip=%s remoteport=%d action=block\n",remote_addr.get_ip(),remote_addr.get_port()); + printf("netsh advfirewall firewall add rule name=udp2raw protocol=UDP dir=out remoteip=%s remoteport=%d action=block\n",remote_addr.get_ip(),remote_addr.get_port()); + } + + if(raw_mode==mode_icmp) + { + printf("netsh advfirewall firewall add rule name=udp2raw protocol=ICMPV6 dir=in remoteip=%s action=block\n",remote_addr.get_ip()); + printf("netsh advfirewall firewall add rule name=udp2raw protocol=ICMPV6 dir=out remoteip=%s action=block\n",remote_addr.get_ip()); + } + } + + myexit(0); + + } + +} +#endif void signal_handler(int sig) { diff --git a/network.cpp b/network.cpp index 8ca1112..3f1156b 100644 --- a/network.cpp +++ b/network.cpp @@ -34,9 +34,11 @@ char if_name[100]=""; char dev[100]=""; unsigned short g_ip_id_counter=0; - +#ifdef UDP2RAW_LINUX unsigned char dest_hw_addr[sizeof(sockaddr_ll::sll_addr)]= {0xff,0xff,0xff,0xff,0xff,0xff,0,0}; +#endif + //{0x00,0x23,0x45,0x67,0x89,0xb9}; const u32_t receive_window_lower_bound=40960; @@ -47,6 +49,7 @@ char g_packet_buf[huge_buf_len]; //looks dirty but works well int g_packet_buf_len=-1; int g_packet_buf_cnt=0; +#ifdef UDP2RAW_LINUX union { sockaddr_ll ll; @@ -54,6 +57,43 @@ union sockaddr_in6 ipv6; }g_sockaddr; socklen_t g_sockaddr_len = -1; +#endif + +#ifdef UDP2RAW_MP + +#ifndef NO_LIBNET +libnet_t *libnet_handle; +libnet_ptag_t g_ptag=0; +int send_with_pcap=0; +#else +int send_with_pcap=1; +#endif + +int pcap_header_captured=0; +int pcap_header_buf[buf_len]; +int pcap_captured_full_len=-1; + +pcap_t *pcap_handle; +int pcap_link_header_len=-1; +//int pcap_cnt=0; +queue_t my_queue; + +pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t pcap_mutex = PTHREAD_MUTEX_INITIALIZER; +int use_pcap_mutex=1; + +ev_async async_watcher; + +struct ev_loop* g_default_loop; + +pthread_t pcap_recv_thread; + +struct bpf_program g_filter; +long long g_filter_compile_cnt=0; + +#endif + +#ifdef UDP2RAW_LINUX struct sock_filter code_tcp_old[] = { { 0x28, 0, 0, 0x0000000c },//0 @@ -218,6 +258,7 @@ tcpdump -i eth1 ip and icmp -dd (010) ret #0 */ +#endif packet_info_t::packet_info_t() { @@ -255,8 +296,94 @@ packet_info_t::packet_info_t() } } +#ifdef UDP2RAW_MP +void my_packet_handler( + u_char *args, + const struct pcap_pkthdr *packet_header, + const u_char *pkt_data +) +{ + /*printf("<%d %d>\n",(int)packet_header->caplen,(int)packet_header->len ); + for(int i=0;i",int( p[i] )); + } + printf("\n");*/ + //mylog(log_debug,"received a packet!\n"); + assert(packet_header->caplen <= packet_header->len); + assert(packet_header->caplen <= max_data_len); + //if(packet_header->caplen > max_data_len) return ; + if(g_fix_gro==0&&packet_header->caplenlen) return; + if((int)packet_header->caplencaplen)); + pthread_mutex_unlock(&queue_mutex); + + //pcap_cnt++; + + ev_async_send (g_default_loop,&async_watcher); + return; +} + +void *pcap_recv_thread_entry(void *none) +{ + struct pcap_pkthdr *packet_header; + const u_char *pkt_data; + + while(1) + { + if(use_pcap_mutex) pthread_mutex_lock(&pcap_mutex); + int ret=pcap_loop(pcap_handle, -1, my_packet_handler, NULL); //use -1 instead of 0 as cnt, since 0 is undefined in old versions + if(use_pcap_mutex) pthread_mutex_unlock(&pcap_mutex); + if(ret==-1) + mylog(log_warn,"pcap_loop exited with value %d\n",ret); + else + { + mylog(log_debug,"pcap_loop exited with value %d\n",ret); + } + ev_sleep(1.0); + //myexit(-1); + } + /* + while(1) + { + //printf("!!!\n"); + pthread_mutex_lock(&pcap_mutex); + int ret=pcap_next_ex(pcap_handle,&packet_header,&pkt_data); + pthread_mutex_unlock(&pcap_mutex); + + switch (ret) + { + case 0: + continue; + case 1: + + break; + + case -1: + mylog(log_fatal,"pcap_next_ex error [%s]\n",pcap_geterr(pcap_handle)); + myexit(-1); + break; + case -2: + assert(0==1);// + break; + default: + assert(0==1);// + } + } + myexit(-1);*/ + return 0; +} + +extern void async_cb(struct ev_loop *loop, struct ev_async *watcher, int revents); +#endif + +#ifdef UDP2RAW_LINUX int init_raw_socket() { assert(raw_ip_version==AF_INET||raw_ip_version==AF_INET6); @@ -381,6 +508,226 @@ int init_raw_socket() return 0; } +#endif +#ifdef UDP2RAW_MP +int init_raw_socket() +{ + +#ifndef NO_LIBNET + char libnet_errbuf[LIBNET_ERRBUF_SIZE]; + + if(raw_ip_version==AF_INET) + { + libnet_handle = libnet_init(LIBNET_RAW4, dev, libnet_errbuf); + } + else + { + assert(raw_ip_version==AF_INET6); + libnet_handle = libnet_init(LIBNET_RAW6, dev, libnet_errbuf); + } + + if(libnet_handle==0) + { + mylog(log_fatal,"libnet_init failed bc of [%s]\n",libnet_errbuf); + myexit(-1); + } + g_ptag=0; + libnet_clear_packet(libnet_handle); +#endif + + char pcap_errbuf[PCAP_ERRBUF_SIZE]; + + //pcap_handle=pcap_open_live(dev,max_data_len,0,1000,pcap_errbuf); + + pcap_handle = pcap_create( dev, pcap_errbuf ); + + + if(pcap_handle==0) + { + mylog(log_fatal,"pcap_create failed bc of [%s]\n",pcap_errbuf); + myexit(-1); + } + + assert( pcap_set_snaplen(pcap_handle, huge_data_len) ==0); + assert( pcap_set_promisc(pcap_handle, 0) ==0); + assert( pcap_set_timeout(pcap_handle, 1) ==0); + assert( pcap_set_immediate_mode(pcap_handle,1) ==0); + + int ret = pcap_activate( pcap_handle ); + if( ret < 0 ) + { + printf("pcap_activate failed %s\n", pcap_geterr(pcap_handle)); + myexit(-1); + } + + if(send_with_pcap) + { + ret=pcap_setdirection(pcap_handle,PCAP_D_INOUT);//must be used after being actived + if(ret!=0) mylog(log_debug,"pcap_setdirection(pcap_handle,PCAP_D_INOUT) failed with value %d, %s\n",ret,pcap_geterr(pcap_handle)); + } + else + { + ret=pcap_setdirection(pcap_handle,PCAP_D_IN); + if(ret!=0) mylog(log_debug,"pcap_setdirection(pcap_handle,PCAP_D_IN) failed with value %d, %s\n",ret,pcap_geterr(pcap_handle)); + } + + + ret=pcap_datalink(pcap_handle); + + if(ret==DLT_EN10MB) + { + pcap_link_header_len=14; + } + else if(ret==DLT_NULL) + { + pcap_link_header_len=4; + } + else if(ret==DLT_LINUX_SLL) + { + pcap_link_header_len=16; + } + else + { + mylog(log_fatal,"unknown pcap link type : %d\n",ret); + myexit(-1); + } + + char filter_exp[1000]; + + address_t tmp_addr; + if(get_src_adress2(tmp_addr,remote_addr)!=0) + { + mylog(log_error,"get_src_adress() failed, maybe you dont have internet\n"); + myexit(-1); + } + + string src=tmp_addr.get_ip(); + string dst=remote_addr.get_ip(); + if(raw_ip_version==AF_INET) + { + //sprintf(filter_exp,"ip and src %s and dst %s and (tcp or udp or icmp)",my_ntoa(source_ip_uint32),dst.c_str()); + sprintf(filter_exp,"ip and src %s and dst %s and (tcp or udp or icmp)",src.c_str(),dst.c_str()); + } + else + { + assert(raw_ip_version==AF_INET6); + sprintf(filter_exp,"ip6 and src %s and dst %s and (tcp or udp or icmp6)",src.c_str(),dst.c_str()); + + } + + if (pcap_compile(pcap_handle, &g_filter, filter_exp, 0, PCAP_NETMASK_UNKNOWN ) == -1) { + printf("Bad filter - %s\n", pcap_geterr(pcap_handle)); + myexit(-1); + } + g_filter_compile_cnt++; + + + if (pcap_setfilter(pcap_handle, &g_filter) == -1) { + printf("Error setting filter - %s\n", pcap_geterr(pcap_handle)); + myexit(-1); + } + +///////////////////////////////////////////////////////////////new thread created here + if(pthread_create(&pcap_recv_thread, NULL, pcap_recv_thread_entry, 0)) { + mylog(log_fatal, "Error creating thread\n"); + myexit(-1); + } +//////////////////////////////////////////////////////////////////////////////// + + + g_ip_id_counter=get_true_random_number()%65535; + + /* + if(lower_level==0) + { + raw_send_fd = socket(AF_INET , SOCK_RAW , IPPROTO_TCP); + + if(raw_send_fd == -1) { + mylog(log_fatal,"Failed to create raw_send_fd\n"); + //perror("Failed to create raw_send_fd"); + myexit(1); + } + + int one = 1; + const int *val = &one; + if (setsockopt (raw_send_fd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) { + mylog(log_fatal,"Error setting IP_HDRINCL %d\n",errno); + //perror("Error setting IP_HDRINCL"); + myexit(2); + } + + + } + else + { + raw_send_fd = socket(PF_PACKET , SOCK_DGRAM , htons(ETH_P_IP)); + + if(raw_send_fd == -1) { + mylog(log_fatal,"Failed to create raw_send_fd\n"); + //perror("Failed to create raw_send_fd"); + myexit(1); + } + //init_ifindex(if_name); + + } + + if(force_socket_buf) + { + if(setsockopt(raw_send_fd, SOL_SOCKET, SO_SNDBUFFORCE, &socket_buf_size, sizeof(socket_buf_size))<0) + { + mylog(log_fatal,"SO_SNDBUFFORCE fail socket_buf_size=%d errno=%s\n",socket_buf_size,strerror(errno)); + myexit(1); + } + } + else + { + if(setsockopt(raw_send_fd, SOL_SOCKET, SO_SNDBUF, &socket_buf_size, sizeof(socket_buf_size))<0) + { + mylog(log_fatal,"SO_SNDBUF fail socket_buf_size=%d errno=%s\n",socket_buf_size,strerror(errno)); + myexit(1); + } + } + + + + //raw_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); + + raw_recv_fd= socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); + + if(raw_recv_fd == -1) { + mylog(log_fatal,"Failed to create raw_recv_fd\n"); + //perror(""); + myexit(1); + } + + if(force_socket_buf) + { + if(setsockopt(raw_recv_fd, SOL_SOCKET, SO_RCVBUFFORCE, &socket_buf_size, sizeof(socket_buf_size))<0) + { + mylog(log_fatal,"SO_RCVBUFFORCE fail socket_buf_size=%d errno=%s\n",socket_buf_size,strerror(errno)); + myexit(1); + } + } + else + { + if(setsockopt(raw_recv_fd, SOL_SOCKET, SO_RCVBUF, &socket_buf_size, sizeof(socket_buf_size))<0) + { + mylog(log_fatal,"SO_RCVBUF fail socket_buf_size=%d errno=%s\n",socket_buf_size,strerror(errno)); + myexit(1); + } + } + + //IP_HDRINCL to tell the kernel that headers are included in the packet + + + + setnonblocking(raw_send_fd); //not really necessary + setnonblocking(raw_recv_fd);*/ + + return 0; +} +#endif +#ifdef UDP2RAW_LINUX void init_filter(int port) { sock_fprog bpf; @@ -450,9 +797,160 @@ void init_filter(int port) myexit(-1); } } +#endif + +#ifdef UDP2RAW_MP +void init_filter(int port) +{ + /* + sock_fprog bpf;*/ + if(raw_mode==mode_faketcp||raw_mode==mode_udp) + { + filter_port=port; + } + + + + char filter_exp[1000]; + + if(raw_ip_version==AF_INET) + { + if(raw_mode==mode_faketcp) + { + sprintf(filter_exp,"ip and tcp and src %s and src port %d and dst port %d",remote_addr.get_ip(),remote_addr.get_port(),port); + } + else if(raw_mode==mode_udp) + { + sprintf(filter_exp,"ip and udp and src %s and src port %d and dst port %d",remote_addr.get_ip(),remote_addr.get_port(),port); + } + else if(raw_mode==mode_icmp) + { + sprintf(filter_exp,"ip and icmp and src %s",remote_addr.get_ip()); + } + else + { + mylog(log_fatal,"unknow raw mode\n"); + myexit(-1); + } + } + else + { + assert(raw_ip_version==AF_INET6); + if(raw_mode==mode_faketcp) + { + sprintf(filter_exp,"ip6 and tcp and src %s and src port %d and dst port %d",remote_addr.get_ip(),remote_addr.get_port(),port); + } + else if(raw_mode==mode_udp) + { + sprintf(filter_exp,"ip6 and udp and src %s and src port %d and dst port %d",remote_addr.get_ip(),remote_addr.get_port(),port); + } + else if(raw_mode==mode_icmp) + { + sprintf(filter_exp,"ip6 and icmp6 and src %s",remote_addr.get_ip()); + } + else + { + mylog(log_fatal,"unknow raw mode\n"); + myexit(-1); + } + } + + mylog(log_info,"filter expression is [%s]\n",filter_exp); + + //pthread_mutex_lock(&pcap_mutex);//not sure if mutex is needed here + + long long tmp_cnt=0; + if(use_pcap_mutex) + { + while(pthread_mutex_trylock(&pcap_mutex)!=0) + { + tmp_cnt++; + pcap_breakloop(pcap_handle); + if(tmp_cnt==100) + { + mylog(log_warn,"%lld attempts of pcap_breakloop()\n", tmp_cnt); + } + if(tmp_cnt%1000==0) + { + mylog(log_warn,"%lld attempts of pcap_breakloop()\n", tmp_cnt); + if(tmp_cnt>5000) + { + mylog(log_fatal,"we might have already run into a deadlock\n"); + } + } + ev_sleep(0.001); + } + mylog(log_info,"breakloop() succeed after %lld attempt(s)\n", tmp_cnt); + } + + if(1) + { + int ret=pcap_setdirection(pcap_handle,PCAP_D_IN); + if(ret!=0) mylog(log_debug,"pcap_setdirection(pcap_handle,PCAP_D_IN) failed with value %d, %s\n",ret,pcap_geterr(pcap_handle)); + } + + assert(g_filter_compile_cnt!=0); + pcap_freecode(&g_filter); + + if (pcap_compile(pcap_handle, &g_filter, filter_exp, 0, PCAP_NETMASK_UNKNOWN ) == -1) { + mylog(log_fatal,"Bad filter - %s\n", pcap_geterr(pcap_handle)); + myexit(-1); + } + g_filter_compile_cnt++; + + if (pcap_setfilter(pcap_handle, &g_filter) == -1) + { + mylog(log_fatal,"Error setting filter - %s\n", pcap_geterr(pcap_handle)); + myexit(-1); + } + + + if(use_pcap_mutex) pthread_mutex_unlock(&pcap_mutex); + /* + if(disable_bpf_filter) return; + //if(raw_mode==mode_icmp) return ; + //code_tcp[8].k=code_tcp[10].k=port; + if(raw_mode==mode_faketcp) + { + bpf.len = sizeof(code_tcp)/sizeof(code_tcp[0]); + code_tcp[code_tcp_port_index].k=port; + bpf.filter = code_tcp; + } + else if(raw_mode==mode_udp) + { + bpf.len = sizeof(code_udp)/sizeof(code_udp[0]); + code_udp[code_udp_port_index].k=port; + bpf.filter = code_udp; + } + else if(raw_mode==mode_icmp) + { + bpf.len = sizeof(code_icmp)/sizeof(code_icmp[0]); + bpf.filter = code_icmp; + } + + int dummy; + + int ret=setsockopt(raw_recv_fd, SOL_SOCKET, SO_DETACH_FILTER, &dummy, sizeof(dummy)); //in case i forgot to remove + if (ret != 0) + { + mylog(log_debug,"error remove fiter\n"); + //perror("filter"); + //exit(-1); + } + ret = setsockopt(raw_recv_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)); + if (ret != 0) + { + mylog(log_fatal,"error set fiter\n"); + //perror("filter"); + myexit(-1); + }*/ +} +#endif + void remove_filter() { filter_port=0; +#ifdef UDP2RAW_LINUX int dummy; int ret=setsockopt(raw_recv_fd, SOL_SOCKET, SO_DETACH_FILTER, &dummy, sizeof(dummy)); if (ret != 0) @@ -461,10 +959,12 @@ void remove_filter() //perror("filter"); //exit(-1); } +#endif } int init_ifindex(const char * if_name,int fd,int &index) { +#ifdef UDP2RAW_LINUX struct ifreq ifr; size_t if_name_len=strlen(if_name); if (if_name_lentos, ntohs(iph->id), ntohs(iph->frag_off), + // iph->ttl , iph->protocol , iph->check , iph->saddr, iph->daddr, + // (const unsigned char *)payload, payloadlen, libnet_handle, g_ptag); + + //assert(g_ptag!=-1 &&g_ptag!=0); + + //int ret; + //ret= libnet_write(libnet_handle); + + //assert(ret!=-1); + + + //iph->tot_len=htons(ip_tot_len); + //iph->check =csum ((unsigned short *) send_raw_ip_buf, iph->ihl*4); + if(raw_ip_version==AF_INET) + { + libnet_write_raw_ipv4(libnet_handle,(const unsigned char *)packet,len); //todo, this api is marked as internal, maybe we should avoid using it. + } + else + { + assert(raw_ip_version==AF_INET6); + libnet_write_raw_ipv6(libnet_handle,(const unsigned char *)packet,len); + } +#endif + } + else + { + char buf[buf_len]; + assert(pcap_header_captured==1); + assert(pcap_link_header_len!=-1); + memcpy(buf,pcap_header_buf,pcap_link_header_len); + memcpy(buf+pcap_link_header_len,packet,len); + //pthread_mutex_lock(&pcap_mutex); looks like this is not necessary, and it harms performance + int ret=pcap_sendpacket(pcap_handle,(const unsigned char *)buf,len+pcap_link_header_len); + if(ret!=0) + { + mylog(log_fatal,"pcap_sendpcaket failed with vaule %d,%s\n",ret,pcap_geterr(pcap_handle)); + //pthread_mutex_unlock(&pcap_mutex); + myexit(-1); + } + //pthread_mutex_unlock(&pcap_mutex); + /* + unsigned char *p=(unsigned char *)send_raw_ip_buf0; + for(int i=0;i",int(p[i])); + printf("\n"); + assert(pcap_sendpacket(pcap_handle,(const unsigned char *)pcap_header_buf,cap_len)==0); + p=(unsigned char *)pcap_header_buf; + for(int i=0;i",int(p[i])); + printf("\n"); + printf("pcap send!\n");*/ + } + return 0; +} +#endif + int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen) { const packet_info_t &send_info=raw_info.send_info; @@ -796,16 +1371,28 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen) iph->daddr = send_info.new_dst_ip.v4; ip_tot_len=sizeof (struct my_iphdr)+payloadlen; +#ifdef UDP2RAW_LINUX if(lower_level)iph->tot_len = htons(ip_tot_len); //this is not necessary ,kernel will always auto fill this //http://man7.org/linux/man-pages/man7/raw.7.html else iph->tot_len = 0; +#endif + +#ifdef UDP2RAW_MP + iph->tot_len = htons(ip_tot_len);//always fill for mp version +#endif memcpy(send_raw_ip_buf+sizeof(my_iphdr) , payload, payloadlen); +#ifdef UDP2RAW_LINUX if(lower_level) iph->check = csum ((unsigned short *) send_raw_ip_buf, iph->ihl*4); //this is not necessary ,kernel will always auto fill this else iph->check=0; +#endif + +#ifdef UDP2RAW_MP + iph->check =csum((unsigned short *) send_raw_ip_buf, iph->ihl*4);//always cal checksum for mp version +#endif } else { @@ -831,6 +1418,7 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen) int pre_recv_raw_packet() { +#ifdef UDP2RAW_LINUX assert(g_packet_buf_cnt==0); g_sockaddr_len=sizeof(g_sockaddr.ll); @@ -876,6 +1464,7 @@ int pre_recv_raw_packet() return -1; } g_packet_buf_cnt++; +#endif return 0; } int discard_raw_packet() @@ -884,6 +1473,7 @@ int discard_raw_packet() g_packet_buf_cnt--; return 0; } +#ifdef UDP2RAW_LINUX int recv_raw_packet(char * &packet,int &len,int peek) { assert(g_packet_buf_cnt==1); @@ -912,6 +1502,19 @@ int recv_raw_packet(char * &packet,int &len,int peek) len=g_packet_buf_len-int(link_level_header_len); return 0; } +#endif +#ifdef UDP2RAW_MP +int recv_raw_packet(char * &packet,int &len,int peek) +{ + assert(g_packet_buf_cnt==1); + if(!peek) + g_packet_buf_cnt--; + + packet=g_packet_buf; + len=g_packet_buf_len; + return 0; +} +#endif int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen) { char *raw_packet_buf; @@ -966,11 +1569,12 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen) return -1; } } - +#ifdef UDP2RAW_LINUX if(lower_level) { memcpy(&recv_info.addr_ll,&g_sockaddr.ll,sizeof(recv_info.addr_ll)); } +#endif @@ -2535,7 +3139,7 @@ int try_to_list_and_bind2(int &fd,address_t address) //try to bind to a port,ma temp_bind_addr.sin_port = htons(port); temp_bind_addr.sin_addr.s_addr = local_ip_uint32;*/ - if (bind(fd, (struct sockaddr*)&address.inner, address.get_len()) !=0) + if (::bind(fd, (struct sockaddr*)&address.inner, address.get_len()) !=0) { mylog(log_debug,"bind fail\n"); return -1; diff --git a/network.h b/network.h index 463bf67..2e00791 100644 --- a/network.h +++ b/network.h @@ -30,6 +30,32 @@ extern int ifindex; extern char g_packet_buf[huge_buf_len]; extern int g_packet_buf_len; extern int g_packet_buf_cnt; +#ifdef UDP2RAW_MP +extern queue_t my_queue; + +extern ev_async async_watcher; +extern struct ev_loop* g_default_loop; + +extern pthread_mutex_t queue_mutex; +extern int use_pcap_mutex; + +extern int pcap_cnt; + +extern int pcap_link_header_len; + +extern int send_with_pcap; +extern int pcap_header_captured; +extern int pcap_header_buf[buf_len]; + +struct icmphdr +{ + uint8_t type; + uint8_t code; + uint16_t check_sum; + uint16_t id; + uint16_t seq; +}; +#endif struct my_iphdr { @@ -212,7 +238,9 @@ struct packet_info_t //todo change this to union bool has_ts; +#ifdef UDP2RAW_LINUX sockaddr_ll addr_ll; +#endif i32_t data_len; @@ -241,7 +269,13 @@ void init_filter(int port); void remove_filter(); +#ifdef UDP2RAW_LINUX int init_ifindex(const char * if_name,int fd,int &index); +#endif + +#ifdef UDP2RAW_MP +int init_ifindex(const char * if_name,int &index); +#endif int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw); diff --git a/server.cpp b/server.cpp index abeaeea..4b6de0a 100644 --- a/server.cpp +++ b/server.cpp @@ -5,6 +5,7 @@ * Author: root */ +#ifndef UDP2RAW_MP #include "common.h" #include "network.h" @@ -911,3 +912,5 @@ int server_event_loop() } return 0; } + +#endif