wangyu před 8 roky
revize
ab2f1bfa93
2 změnil soubory, kde provedl 961 přidání a 0 odebrání
  1. 21 0
      LICENSE.md
  2. 940 0
      main.cpp

+ 21 - 0
LICENSE.md

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Yu Wang (wangyucn at gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 940 - 0
main.cpp

@@ -0,0 +1,940 @@
+#include<stdio.h>
+#include<string.h>
+#include<sys/socket.h>
+#include<arpa/inet.h>
+#include<stdlib.h>
+#include<getopt.h>
+#include <unistd.h>
+#include<errno.h>
+
+#include <fcntl.h>
+//#include"aes.h"
+
+#include <sys/epoll.h>
+#include <sys/wait.h>
+
+#include<map>
+#include<string>
+#include<vector>
+
+
+#include <sys/socket.h>    //for socket ofcourse
+#include <sys/types.h>
+#include <stdlib.h> //for exit(0);
+#include <errno.h> //For errno - the error number
+#include <netinet/tcp.h>   //Provides declarations for tcp header
+#include <netinet/ip.h>    //Provides declarations for ip header
+#include <netinet/if_ether.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <byteswap.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <linux/if_ether.h>
+#include <linux/filter.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <sys/timerfd.h>
+
+using namespace std;
+
+char local_address[100], remote_address[100],source_address[100];
+int local_port = -1, remote_port = -1,source_port;
+
+const int buf_len = 20480;
+
+const int server_mode=2;
+const int client_mode=1;
+int prog_mode=0; //0 unset; 1client 2server
+const int RETRY_TIME=3;
+
+void handler(int num) {
+	int status;
+	int pid;
+	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+		if (WIFEXITED(status)) {
+			//printf("The child exit with code %d",WEXITSTATUS(status));
+		}
+	}
+}
+
+void setnonblocking(int sock) {
+	int opts;
+	opts = fcntl(sock, F_GETFL);
+
+	if (opts < 0) {
+		perror("fcntl(sock,GETFL)");
+		exit(1);
+	}
+	opts = opts | O_NONBLOCK;
+	if (fcntl(sock, F_SETFL, opts) < 0) {
+		perror("fcntl(sock,SETFL,opts)");
+		exit(1);
+	}
+
+}
+
+int udp_fd;
+int raw_recv_fd;
+int raw_send_fd;
+int init_raw_socket()
+{
+	raw_send_fd = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
+    if(raw_send_fd == -1) {
+        perror("Failed to create raw_send_fd");
+        exit(1);
+    }
+	//raw_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));
+
+	raw_recv_fd= socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
+	//raw_fd=socket(AF_PACKET , SOCK_RAW , htons(ETH_P_IP));
+    // packet_recv_sd = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
+    if(raw_recv_fd == -1) {
+        //socket creation failed, may be because of non-root privileges
+        perror("Failed to create raw_recv_fd");
+        exit(1);
+    }
+
+    //IP_HDRINCL to tell the kernel that headers are included in the packet
+
+    int one = 1;
+    const int *val = &one;
+    if (setsockopt (raw_send_fd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) {
+        perror("Error setting IP_HDRINCL");
+        exit(2);
+    }
+	return 0;
+}
+char buf[buf_len];
+char buf2[buf_len];
+char raw_send_buf[buf_len];
+char raw_send_buf2[buf_len];
+struct sock_filter code[] = {
+		{ 0x28, 0, 0, 0x0000000c },//0
+		{ 0x15, 0, 10, 0x00000800 },//1
+		{ 0x30, 0, 0, 0x00000017 },//2
+		{ 0x15, 0, 8, 0x00000006 },//3
+		{ 0x28, 0, 0, 0x00000014 },//4
+		{ 0x45, 6, 0, 0x00001fff },//5
+		{ 0xb1, 0, 0, 0x0000000e },//6
+		{ 0x48, 0, 0, 0x0000000e },//7
+		{ 0x15, 2, 0, 0x0000ef32 },//8
+		{ 0x48, 0, 0, 0x00000010 },//9
+		{ 0x15, 0, 1, 0x0000ef32 },//10
+		{ 0x6, 0, 0, 0x0000ffff },//11
+		{ 0x6, 0, 0, 0x00000000 },//12
+};
+sock_fprog bpf;
+long long get_current_time()
+{
+	timespec tmp_time;
+	clock_gettime(CLOCK_MONOTONIC, &tmp_time);
+	return tmp_time.tv_sec*1000+tmp_time.tv_nsec/(1000*1000ll);
+}
+void init_filter(int port)
+{
+	code[8].k=code[10].k=port;
+	bpf.len = sizeof(code)/sizeof(code[0]);
+	bpf.filter = code;
+	//printf("<%d>\n",bpf.len);
+	int ret = setsockopt(raw_recv_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));
+	memset(code,0,sizeof(code));
+	if (ret != 0)
+	{
+		printf("error set fiter\n");
+		exit(-1);
+	}
+}
+void process_arg(int argc, char *argv[])
+{
+	int i,j,k,opt;
+    static struct option long_options[] =
+      {
+        /* These options set a flag. */
+        {"source", required_argument,    0, 1},
+      };
+    int option_index = 0;
+	printf("argc=%d ", argc);
+	for (i = 0; i < argc; i++)
+		printf("%s ", argv[i]);
+	printf("\n");
+
+	if (argc == 1)
+	{
+		printf(
+				"proc -l [adress:]port -r [adress:]port  [-a passwd] [-b passwd]\n");
+		exit(-1);
+	}
+
+	int no_l = 1, no_r = 1;
+	while ((opt = getopt_long(argc, argv, "l:r:sch",long_options,&option_index)) != -1) {
+		//string opt_key;
+		//opt_key+=opt;
+		switch (opt) {
+		case 'l':
+			no_l = 0;
+			if (strchr(optarg, ':') != 0) {
+				sscanf(optarg, "%[^:]:%d", local_address, &local_port);
+			} else {
+				strcpy(local_address, "127.0.0.1");
+				sscanf(optarg, "%d", &local_port);
+			}
+			break;
+		case 'r':
+			no_r = 0;
+			if (strchr(optarg, ':') != 0) {
+				sscanf(optarg, "%[^:]:%d", remote_address, &remote_port);
+			} else {
+				strcpy(remote_address, "127.0.0.1");
+				sscanf(optarg, "%d", &remote_port);
+			}
+			break;
+		case 's':
+			if(prog_mode==0)
+			{
+				prog_mode=server_mode;
+			}
+			else
+			{
+				printf("-s /-c has already been set,-s option conflict");
+				exit(-1);
+			}
+			break;
+		case 'c':
+			if(prog_mode==0)
+			{
+				prog_mode=client_mode;
+			}
+			else
+			{
+				printf("-s /-c has already been set,-c option conflict");
+				exit(-1);
+			}
+			break;
+		case 'h':
+			break;
+		case 1:
+			if (strchr(optarg, ':') != 0) {
+				sscanf(optarg, "%[^:]:%d", source_address, &source_port);
+				printf("source: %s:%d",source_address,&source_port);
+			} else {
+				printf("format --source ip:adress");
+				exit(-1);
+			}
+			break;
+
+		default:
+			printf("ignore unknown <%s>", optopt);
+		}
+	}
+
+	if (no_l)
+		printf("error: -i not found\n");
+	if (no_r)
+		printf("error: -o not found\n");
+	if(prog_mode==0)
+		printf("error: -s /-r  hasnt been set\n");
+	if (no_l || no_r||prog_mode==0)
+	{
+		exit(-1);
+	}
+}
+
+int recv_raw()
+{
+}
+struct packet_info_t
+{
+	//ip_part:
+	uint32_t src_ip;
+	uint16_t src_port;
+	uint32_t dst_ip;
+	uint16_t dst_port;
+
+	//tcp_part:
+	bool syn,ack,psh;
+	uint32_t seq,ack_seq;
+
+
+}g_packet_info;
+
+struct pseudo_header {
+    u_int32_t source_address;
+    u_int32_t dest_address;
+    u_int8_t placeholder;
+    u_int8_t protocol;
+    u_int16_t tcp_length;
+};
+/*
+    Generic checksum calculation function
+*/
+unsigned short csum(unsigned short *ptr,int nbytes) {
+    register long sum;
+    unsigned short oddbyte;
+    register short answer;
+
+    sum=0;
+    while(nbytes>1) {
+        sum+=*ptr++;
+        nbytes-=2;
+    }
+    if(nbytes==1) {
+        oddbyte=0;
+        *((u_char*)&oddbyte)=*(u_char*)ptr;
+        sum+=oddbyte;
+    }
+
+    sum = (sum>>16)+(sum & 0xffff);
+    sum = sum + (sum>>16);
+    answer=(short)~sum;
+
+    return(answer);
+}
+
+int send_raw(packet_info_t &info,char * payload,int payloadlen)
+{
+	char *data;
+
+    memset(raw_send_buf,0,payloadlen+100);
+
+    struct iphdr *iph = (struct iphdr *) raw_send_buf;
+
+    //TCP header
+    struct tcphdr *tcph = (struct tcphdr *) (raw_send_buf + sizeof (struct ip));
+    struct sockaddr_in sin;
+    struct pseudo_header psh;
+
+    //Data part
+    data = raw_send_buf + sizeof(struct iphdr) + sizeof(struct tcphdr);
+
+    memcpy(data , payload, payloadlen);
+
+    //some address resolution
+    sin.sin_family = AF_INET;
+    sin.sin_port = htons(info.dst_port);
+    sin.sin_addr.s_addr = info.dst_ip;
+
+    //Fill in the IP Header
+    iph->ihl = 5;
+    iph->version = 4;
+    iph->tos = 0;
+    iph->tot_len = sizeof (struct iphdr) + sizeof (struct tcphdr) + payloadlen;
+    iph->id = htonl (54321); //Id of this packet
+    iph->frag_off = 0;
+    iph->ttl = 255;
+    iph->protocol = IPPROTO_TCP;
+    iph->check = 0; //Set to 0 before calculating checksum
+    iph->saddr = info.src_ip;    //Spoof the source ip address
+    iph->daddr = info.dst_ip;
+
+    //TCP Header
+    tcph->source = htons(info.src_port);
+    tcph->dest = htons(info.dst_port);
+
+    tcph->seq =htonl(info.seq);
+    tcph->ack_seq = htonl(info.ack);
+
+    tcph->doff = 5;  //tcp header size
+    tcph->fin=0;
+    tcph->syn=info.syn;
+    tcph->rst=0;
+    tcph->psh=info.psh;
+    tcph->ack=info.ack;
+
+    tcph->urg=0;
+    tcph->window = htons((uint16_t)129600);
+    tcph->check = 0; //leave checksum 0 now, filled later by pseudo header
+    tcph->urg_ptr = 0;
+
+    psh.source_address = info.src_ip;
+    psh.dest_address = sin.sin_addr.s_addr;
+    psh.placeholder = 0;
+    psh.protocol = IPPROTO_TCP;
+    psh.tcp_length = htons(sizeof(struct tcphdr) + payloadlen );
+
+    int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + payloadlen;
+
+     memcpy(raw_send_buf2 , (char*) &psh , sizeof (struct pseudo_header));
+     memcpy(raw_send_buf2 + sizeof(struct pseudo_header) , tcph , sizeof(struct tcphdr) + payloadlen);
+
+     tcph->check = csum( (unsigned short*) raw_send_buf2, psize);
+
+     //Ip checksum
+     iph->check = csum ((unsigned short *) raw_send_buf, iph->tot_len);
+
+     int ret = sendto(raw_send_fd, raw_send_buf, iph->tot_len ,  0, (struct sockaddr *) &sin, sizeof (sin));
+	 printf("<ret:%d>\n",ret);
+	 if(ret<0)
+     {
+
+    	 perror("raw send error");
+    	 //printf("send error\n");
+     }
+     return 0;
+}
+int send_sync()
+{
+	g_packet_info.seq=0;
+	g_packet_info.ack=0;
+	g_packet_info.syn=1;
+	g_packet_info.ack_seq=0;
+	g_packet_info.psh=0;
+	send_raw(g_packet_info,0,0);
+	return 0;
+}
+const int client_nothing=0;
+const int client_syn_sent=1;
+const int client_ack_sent=2;
+const int client_ready=3;
+int client_current_state=client_nothing;
+int retry_counter;
+
+long long last_state_time;
+uint32_t session_id;
+
+uint32_t get_true_random_number()
+{
+	uint32_t ret;
+	int fd=open("/dev/urandom",O_RDONLY);
+	read(fd,&ret,sizeof(ret));
+	return htonl(ret);
+}
+const int server_nothing=0;
+const int server_syn_ack_sent=1;
+const int server_heartbeat_sent=2;
+const int server_ready=3;
+int server_current_state=server_nothing;
+long long last_hb_recv_time;
+int fake_tcp_keep_connection_client() //for client
+{
+	//printf("timer!");
+	//fflush(stdout);
+	begin:
+	if(client_current_state==client_nothing)
+	{
+		send_sync(/*sync*/);//send sync
+		client_current_state=client_syn_sent;
+		last_state_time=get_current_time();
+		printf("state changed from nothing to syn_sent\n");
+		retry_counter=RETRY_TIME;
+
+	}
+	if(client_current_state==client_syn_sent  &&get_current_time()-last_state_time>1000ll)
+	{
+		if(retry_counter==0)
+		{
+			client_current_state=client_nothing;
+			goto begin;
+		}
+		else
+		{
+			retry_counter--;
+			printf("retry send sync\n");
+			send_sync(/*sync*/);//send sync again
+			last_state_time=get_current_time();
+		}
+	}
+	if(client_current_state==client_ack_sent &&get_current_time()-last_state_time>1000)
+	{
+		printf("!!!!!\n");
+		fflush(stdout);
+		if(retry_counter==0)
+		{
+			client_current_state=client_nothing;
+			goto begin;
+		}
+		else
+		{
+			retry_counter--;
+			send_raw(g_packet_info,0,0);
+			last_state_time=get_current_time();
+			printf("retry send ack  counter left:%d\n",retry_counter);
+			fflush(stdout);
+		}
+	}
+
+	if(client_current_state==client_ready)
+	{
+		printf("time %lld %lld\n",get_current_time(),last_state_time);
+		if(get_current_time()-last_hb_recv_time>5*1000ll)
+		{
+			client_current_state=client_nothing;
+			return 0;
+		}
+		g_packet_info.syn=0;
+		g_packet_info.ack=1;
+		printf("heartbeat sent\n");
+		send_raw(g_packet_info,"hb",strlen("hb"));
+		//last_time=get_current_time();
+	}
+
+}
+
+int fake_tcp_keep_connection_server()
+{
+	//begin:
+	printf("timerxxxx!\n");
+	fflush(stdout);
+	if(server_current_state==server_nothing)
+	{
+		return 0;
+	}
+	if(server_current_state==server_syn_ack_sent &&get_current_time()-last_state_time>1000ll )
+	{
+		if(retry_counter==0)
+		{
+			server_current_state=server_nothing;
+			//send_raw(g_packet_info,0,0);
+		}
+		else
+		{
+			retry_counter--;
+			send_raw(g_packet_info,0,0);
+			last_state_time=get_current_time();
+			printf("resend syn ack\n");
+		}
+		//send_raw(/*syn ack*/);
+	}
+	if(server_current_state==server_heartbeat_sent||server_current_state==server_ready)
+	{
+		if(get_current_time()-last_hb_recv_time>5*1000ll)
+		{
+			printf("%lld %lld",get_current_time(),last_state_time);
+			server_current_state=server_nothing;
+			printf("changed state to server_nothing111\n");
+			return 0;
+		}
+
+		g_packet_info.syn=0;
+		g_packet_info.ack=1;
+		g_packet_info.psh=1;
+		send_raw(g_packet_info,"hb",strlen("hb"));
+		//last_time=get_current_time();
+		printf("heart beat sent,fffff\n");
+		fflush(stdout);
+	}
+
+}
+struct sockaddr_in udp_old_addr_in;
+
+
+
+int set_timer(int epollfd,int &timer_fd)
+{
+	int ret;
+	epoll_event ev;
+
+	itimerspec its;
+	memset(&its,0,sizeof(its));
+
+	if((timer_fd=timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0)
+	{
+		printf("timer_fd create error");
+		exit(1);
+	}
+	its.it_interval.tv_sec=1;
+	its.it_value.tv_sec=1;
+	timerfd_settime(timer_fd,0,&its,0);
+
+
+	ev.events = EPOLLIN;
+	ev.data.fd = timer_fd;
+
+	epoll_ctl(epollfd, EPOLL_CTL_ADD, timer_fd, &ev);
+	if (ret < 0) {
+		printf("epoll_ctl return %d\n", ret);
+		exit(-1);
+	}
+}
+
+const int MTU=1440;
+int client_recv(iphdr * iph,tcphdr *tcph,char * data,int data_len)
+{
+
+	if(client_current_state==client_syn_sent )
+	{
+		if (!(tcph->syn==1&&tcph->ack==1)) return 0;
+		if(iph->saddr!=g_packet_info.dst_ip||ntohs(tcph->source)!=g_packet_info.dst_port)
+		{
+			printf("unexpected adress %d %d  %d %d\n",iph->saddr,g_packet_info.dst_ip,ntohl(tcph->source),g_packet_info.dst_port);
+			return 0;
+		}
+
+		g_packet_info.ack_seq=ntohl(tcph->ack_seq)+1;
+		g_packet_info.psh=0;
+		g_packet_info.syn=0;
+		g_packet_info.ack=1;
+		g_packet_info.seq+=1;
+
+		printf("sent ack back\n");
+		fflush(stdout);
+		send_raw(g_packet_info,0,0);
+		client_current_state=client_ack_sent;
+		printf("changed state to client_ack_sent\n");
+		last_state_time=get_current_time();
+		retry_counter=RETRY_TIME;
+	}
+	if(client_current_state==client_ack_sent )
+	{
+		//printf(" i m here\n");
+		//fflush(stdout);
+		if( tcph->syn==1||tcph->ack!=1 )
+		{
+			printf("unexpected syn ack");
+			return 0;
+		}
+		if(iph->saddr!=g_packet_info.dst_ip||ntohs(tcph->source)!=g_packet_info.dst_port)
+		{
+			printf("unexpected adress\n");
+			return 0;
+		}
+		client_current_state=client_ready;
+		printf("changed state to client_ready\n");
+		//send_raw(g_packet_info,"hb",strlen("hb"));
+	}
+	if(client_current_state==client_ready )
+	{
+		printf("heart beat received\n");
+		last_hb_recv_time=get_current_time();
+	}
+}
+int send_heart_beat(packet_info_t &info)
+{
+
+}
+int server_recv(iphdr * iph,tcphdr *tcph,char * data,int data_len)
+{
+	if(server_current_state==server_nothing)
+	{
+		if(!( tcph->syn==1&&tcph->ack==0 )) return 0;
+
+		g_packet_info.dst_port=ntohs(tcph->source);
+		g_packet_info.dst_ip=iph->saddr;
+
+		g_packet_info.ack_seq=ntohl(tcph->ack_seq)+1;
+		g_packet_info.psh=0;
+		g_packet_info.syn=1;
+		g_packet_info.ack=1;
+		g_packet_info.seq;//dont need to set
+		printf("sent syn ack\n");
+		fflush(stdout);
+		send_raw(g_packet_info,0,0);
+		server_current_state=server_syn_ack_sent;
+		printf("changed state to server_syn_ack_sent\n");
+		retry_counter=RETRY_TIME;
+		last_state_time=get_current_time();
+	}
+	else if(server_current_state==server_syn_ack_sent)
+	{
+		if(!( tcph->syn==0&&tcph->ack==1 )) return 0;
+
+
+		server_current_state=server_heartbeat_sent;
+		g_packet_info.syn=0;
+		g_packet_info.ack=1;
+
+		send_raw(g_packet_info,"hb",strlen("hb"));
+		printf("changed state to server_heartbeat_sent\n");
+
+		last_hb_recv_time=get_current_time(); //this ack is counted as hearbeat
+		last_state_time=get_current_time();
+	}
+	else if(server_current_state==server_heartbeat_sent)//heart beat received
+	{
+		if( tcph->syn==1||tcph->ack!=1 )  return 0;
+		if(iph->saddr!=g_packet_info.dst_ip||ntohs(tcph->source)!=g_packet_info.dst_port)
+		{
+			printf("unexpected adress\n");
+			return 0;
+		}
+		server_current_state=server_ready;
+		last_state_time=get_current_time();
+		last_hb_recv_time=get_current_time();
+		printf("changed state to server_ready\n");
+
+	}
+	else if(server_current_state==server_ready)
+	{
+		if( tcph->syn==1||tcph->ack!=1 )  return 0;
+		if(iph->saddr!=g_packet_info.dst_ip||ntohs(tcph->source)!=g_packet_info.dst_port)
+		{
+			printf("unexpected adress\n");
+			return 0;
+		}
+		printf("heart beat received\n");
+		last_hb_recv_time=get_current_time();
+	}
+}
+
+
+int on_raw_recv()
+{
+	int size;
+	struct sockaddr saddr;
+	socklen_t saddr_size;
+	saddr_size = sizeof(saddr);
+
+	printf("raw!\n");
+	fflush(stdout);
+
+	size = recvfrom(raw_recv_fd, buf, buf_len, 0 ,&saddr , &saddr_size);
+
+	char *ip_data=buf+14;
+
+	struct iphdr *iph = (struct iphdr *) (ip_data);
+
+
+    if (!(iph->ihl > 0 && iph->ihl < (MTU)/4)) {
+    	printf("iph ihl error");
+    	fflush(stdout);
+        return 0;
+    }
+
+    if (iph->protocol != IPPROTO_TCP) {
+    	printf("iph protocal != tcp\n");
+    	fflush(stdout);
+    	return 0;
+    }
+
+
+	int ip_len=ntohs(iph->tot_len);
+
+    unsigned short iphdrlen =iph->ihl*4;
+    struct tcphdr *tcph=(struct tcphdr*)(ip_data+ iphdrlen);
+    unsigned short tcphdrlen = tcph->doff*4;
+
+    if (!(tcph->doff > 0 && tcph->doff < (MTU - iphdrlen)/4)) {
+    	printf("tcph error");
+    	fflush(stdout);
+    	return 0;
+    }
+
+    int data_len = ip_len-tcphdrlen-iphdrlen;
+
+    char *data=ip_data+tcphdrlen+iphdrlen;
+
+    //printf("%d\n",ip_len);
+    /*
+    for(int i=0;i<size;i++)
+    {
+    	printf("<%x>",(unsigned char)buf[i]);
+
+    }
+	  printf("\n");
+
+    for(int i=0;i<data_len;i++)
+    {
+    	printf("<%x>",(unsigned char)data[i]);
+    }*/
+
+    printf("\n");
+	printf("<%u,%u,%u,%u,%d>\n",(unsigned int)iphdrlen,(unsigned int)tcphdrlen,(unsigned int)tcph->syn,(unsigned int)tcph->ack,data_len);
+	fflush(stdout);
+
+	if(prog_mode==server_mode)
+	{
+		server_recv(iph,tcph,data,data_len);
+	}
+	else
+	{
+		client_recv(iph,tcph,data,data_len);
+	}
+	return 0;
+}
+int client()
+{
+	int i, j, k;int ret;
+	init_raw_socket();
+	session_id=get_true_random_number();
+
+	init_filter(source_port);
+	g_packet_info.dst_ip=inet_addr(remote_address);
+	g_packet_info.dst_port=remote_port;
+
+	g_packet_info.src_ip=inet_addr(source_address);
+	g_packet_info.src_port=source_port;
+
+	int udp_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;
+
+	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 = inet_addr(local_address);
+	if (bind(udp_fd, (struct sockaddr*) &local_me, slen) == -1) {
+		perror("socket bind error");
+		exit(1);
+	}
+	setnonblocking(udp_fd);
+	int epollfd = epoll_create1(0);
+	const int max_events = 4096;
+	struct epoll_event ev, events[max_events];
+	if (epollfd < 0) {
+		printf("epoll return %d\n", epollfd);
+		exit(-1);
+	}
+	ev.events = EPOLLIN;
+	ev.data.fd = udp_fd;
+	ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, udp_fd, &ev);
+	if (ret!=0) {
+		printf("add  udp_listen_fd error\n");
+		exit(-1);
+	}
+	ev.events = EPOLLIN;
+	ev.data.fd = raw_recv_fd;
+
+	ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, raw_recv_fd, &ev);
+	if (ret!= 0) {
+		printf("add raw_fd error\n");
+		exit(-1);
+	}
+
+	////add_timer for fake_tcp_keep_connection_client
+
+	//sleep(10);
+
+	memset(&udp_old_addr_in,0,sizeof(sockaddr_in));
+	int unbind=1;
+	int timer_fd;
+
+	set_timer(epollfd,timer_fd);
+	while(1)////////////////////////
+	{
+		int nfds = epoll_wait(epollfd, events, max_events, 180 * 1000);
+		if (nfds < 0) {  //allow zero
+			printf("epoll_wait return %d\n", nfds);
+			exit(-1);
+		}
+		int n;
+		for (n = 0; n < nfds; ++n) {
+			if (events[n].data.fd == raw_recv_fd)
+			{
+				on_raw_recv();
+				/*if(is_sync_ack)
+				{
+
+				}
+				else if(is heart_beat)
+				{
+
+				}
+				else if(is_data)
+				{
+					sendto();
+				}*/
+			}
+			if(events[n].data.fd ==timer_fd)
+			{
+				//printf("timer!\n");
+				//fflush(stdout);
+				uint64_t value;
+				read(timer_fd, &value, 8);
+				fake_tcp_keep_connection_client();
+			}
+			if (events[n].data.fd == udp_fd)
+			{
+				socklen_t recv_len;
+				struct sockaddr_in udp_new_addr_in;
+				if ((recv_len = recvfrom(udp_fd, buf, buf_len, 0,
+						(struct sockaddr *) &udp_new_addr_in, &slen)) == -1) {
+					printf("recv_from error");
+					exit(1);
+				}
+				printf("Received packet from %s:%d\n", inet_ntoa(udp_new_addr_in.sin_addr),
+						ntohs(udp_new_addr_in.sin_port));
+				fflush(stdout);
+				if(udp_old_addr_in.sin_addr.s_addr==0&&udp_old_addr_in.sin_port==0)
+				{
+					memcpy(&udp_old_addr_in,&udp_new_addr_in,sizeof(udp_new_addr_in));
+				}
+				else if(udp_new_addr_in.sin_addr.s_addr!=udp_old_addr_in.sin_addr.s_addr
+						||udp_new_addr_in.sin_port!=udp_old_addr_in.sin_port)
+				{
+					printf("new <ip,port> connected in,ignore\n");
+					fflush(stdout);
+					continue;
+				}
+				////send_data_raw(buf,recv_len);
+			}
+		}
+	}
+	return 0;
+}
+int server()
+{
+	int i, j, k;int ret;
+	init_raw_socket();
+	init_filter(local_port);
+	int epollfd = epoll_create1(0);
+	const int max_events = 4096;
+
+	g_packet_info.src_ip=inet_addr(local_address);
+	g_packet_info.src_port=local_port;
+
+	struct epoll_event ev, events[max_events];
+	if (epollfd < 0) {
+		printf("epoll return %d\n", epollfd);
+		exit(-1);
+	}
+
+	ev.events = EPOLLIN;
+	ev.data.fd = raw_recv_fd;
+
+	ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, raw_recv_fd, &ev);
+	if (ret!= 0) {
+		printf("add raw_fd error\n");
+		exit(-1);
+	}
+	int timer_fd;
+	set_timer(epollfd,timer_fd);
+	while(1)////////////////////////
+	{
+		int nfds = epoll_wait(epollfd, events, max_events, 180 * 1000);
+		if (nfds < 0) {  //allow zero
+			printf("epoll_wait return %d\n", nfds);
+			exit(-1);
+		}
+		int n;
+		const int MTU=1440;
+		for (n = 0; n < nfds; ++n)
+		{
+			printf("%d %d %d %d\n",timer_fd,raw_recv_fd,raw_send_fd,n);
+			if (events[n].data.fd == timer_fd)
+			{
+				uint64_t value;
+				read(timer_fd, &value, 8);
+				fake_tcp_keep_connection_server();
+			}
+			if (events[n].data.fd == raw_recv_fd)
+			{
+				on_raw_recv();
+			}
+		}
+	}
+	return 0;
+}
+int main(int argc, char *argv[])
+{
+	int i, j, k;
+
+	signal(SIGCHLD, handler);
+	process_arg(argc,argv);
+
+	if(prog_mode==client_mode)
+	{
+		client();
+	}
+	else
+	{
+		server();
+	}
+
+	return 0;
+}