wangyu- 8 年 前
コミット
3960ca1b36
7 ファイル変更1077 行追加991 行削除
  1. 5 2
      common.h
  2. 31 0
      connection.cpp
  3. 7 0
      connection.h
  4. 2 988
      main.cpp
  5. 1 1
      makefile
  6. 976 0
      misc.cpp
  7. 55 0
      misc.h

+ 5 - 2
common.h

@@ -47,8 +47,11 @@
 #include <pthread.h>
 
 #include<unordered_map>
-#include<vector>
-#include<string>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
 using  namespace std;
 
 

+ 31 - 0
connection.cpp

@@ -15,6 +15,7 @@ const int disable_conv_clear=0;//a udp connection in the multiplexer is called c
 
 const int disable_conn_clear=0;//a raw connection is called conn.
 
+conn_manager_t conn_manager;
 
 	anti_replay_seq_t anti_replay_t::get_new_seq_for_send()
 	{
@@ -713,3 +714,33 @@ int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len)///safer t
 
 	return parse_safer(conn_info,recv_data,recv_len,type,data,len);
 }
+
+void server_clear_function(u64_t u64)//used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),
+//so we have to close the fd when conv expires
+{
+	int fd=int(u64);
+	int ret;
+	assert(fd!=0);
+	/*
+	epoll_event ev;
+
+	ev.events = EPOLLIN;
+	ev.data.u64 = u64;
+
+	ret = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &ev);
+	if (ret!=0)
+	{
+		mylog(log_fatal,"fd:%d epoll delete failed!!!!\n",fd);
+		myexit(-1);   //this shouldnt happen
+	}*/                //no need
+	ret= close(fd);  //closed fd should be auto removed from epoll
+
+	if (ret!=0)
+	{
+		mylog(log_fatal,"close fd %d failed !!!!\n",fd);
+		myexit(-1);  //this shouldnt happen
+	}
+	//mylog(log_fatal,"size:%d !!!!\n",conn_manager.udp_fd_mp.size());
+	assert(conn_manager.udp_fd_mp.find(fd)!=conn_manager.udp_fd_mp.end());
+	conn_manager.udp_fd_mp.erase(fd);
+}

+ 7 - 0
connection.h

@@ -14,6 +14,9 @@ extern int disable_anti_replay;
 #include "common.h"
 #include "log.h"
 #include "network.h"
+#include "misc.h"
+
+
 
 struct anti_replay_t  //its for anti replay attack,similar to openvpn/ipsec 's anti replay window
 {
@@ -142,6 +145,10 @@ int clear_inactive0();
 
 };
 
+extern conn_manager_t conn_manager;
+
+void server_clear_function(u64_t u64);
+
 int send_bare(raw_info_t &raw_info,const char* data,int len);//send function with encryption but no anti replay,this is used when client and server verifys each other
 //you have to design the protocol carefully, so that you wont be affect by relay attack
 int reserved_parse_bare(const char *input,int input_len,char* & data,int & len); // a sub function used in recv_bare

+ 2 - 988
main.cpp

@@ -1,52 +1,16 @@
 #include "common.h"
 #include "network.h"
 #include "connection.h"
+#include "misc.h"
 #include "log.h"
 #include "lib/md5.h"
 #include "encrypt.h"
-#include "git_version.h"
-#include <fstream>
-#include <string>
-#include <vector>
-#include <map>
-#include <set>
-
-char local_ip[100]="0.0.0.0", remote_ip[100]="255.255.255.255",source_ip[100]="0.0.0.0";//local_ip is for -l option,remote_ip for -r option,source for --source-ip
-u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.
-int local_port = -1, remote_port=-1,source_port=0;//similiar to local_ip  remote_ip,buf for port.source_port=0 indicates --source-port is not enabled
-
-int force_source_ip=0; //if --source-ip is enabled
-
-
-id_t const_id=0;//an id used for connection recovery,its generated randomly,it never change since its generated
-
-
-
-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
-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.
-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
-
-
-int simple_rule=0;  //deprecated.
-int keep_rule=0; //whether to monitor the iptables rule periodly,re-add if losted
-int auto_add_iptables_rule=0;//if -a is set
-int generate_iptables_rule=0;//if -g is set
-int generate_iptables_rule_add=0;// if --gen-add is set
-
-int debug_resend=0; // debug only
-
-char key_string[1000]= "secret key";// -k option
-
 
 int mtu_warn=1375;//if a packet larger than mtu warn is receviced,there will be a warning
 
 //uint64_t current_time_rough=0;
 
-conn_manager_t conn_manager;
+
 int VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV;
 ////////==============================variable divider=============================================================
 
@@ -58,106 +22,13 @@ int server_on_raw_recv_pre_ready(conn_info_t &conn_info,char * ip_port,u32_t tmp
 int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char type,char *data,int data_len);
 int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * data, int data_len);
 
-void process_arg(int argc, char *argv[]);
-int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw);
 int DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;
 ////////////////=======================declear divider=============================
 
-void server_clear_function(u64_t u64)//used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),
-//so we have to close the fd when conv expires
-{
-	int fd=int(u64);
-	int ret;
-	assert(fd!=0);
-	/*
-	epoll_event ev;
-
-	ev.events = EPOLLIN;
-	ev.data.u64 = u64;
-
-	ret = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &ev);
-	if (ret!=0)
-	{
-		mylog(log_fatal,"fd:%d epoll delete failed!!!!\n",fd);
-		myexit(-1);   //this shouldnt happen
-	}*/                //no need
-	ret= close(fd);  //closed fd should be auto removed from epoll
-
-	if (ret!=0)
-	{
-		mylog(log_fatal,"close fd %d failed !!!!\n",fd);
-		myexit(-1);  //this shouldnt happen
-	}
-	//mylog(log_fatal,"size:%d !!!!\n",conn_manager.udp_fd_mp.size());
-	assert(conn_manager.udp_fd_mp.find(fd)!=conn_manager.udp_fd_mp.end());
-	conn_manager.udp_fd_mp.erase(fd);
-}
-
 
 
 
 
-
-int set_timer(int epollfd,int &timer_fd)//put a timer_fd into epoll,general function,used both in client and server
-{
-	int ret;
-	epoll_event ev;
-
-	itimerspec its;
-	memset(&its,0,sizeof(its));
-
-	if((timer_fd=timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0)
-	{
-		mylog(log_fatal,"timer_fd create error\n");
-		myexit(1);
-	}
-	its.it_interval.tv_sec=(timer_interval/1000);
-	its.it_interval.tv_nsec=(timer_interval%1000)*1000ll*1000ll;
-	its.it_value.tv_nsec=1; //imidiately
-	timerfd_settime(timer_fd,0,&its,0);
-
-
-	ev.events = EPOLLIN;
-	ev.data.u64 = timer_fd;
-
-	ret=epoll_ctl(epollfd, EPOLL_CTL_ADD, timer_fd, &ev);
-	if (ret < 0) {
-		mylog(log_fatal,"epoll_ctl return %d\n", ret);
-		myexit(-1);
-	}
-	return 0;
-}
-
-
-int set_timer_server(int epollfd,int &timer_fd)//only for server
-{
-	int ret;
-	epoll_event ev;
-
-	itimerspec its;
-	memset(&its,0,sizeof(its));
-
-	if((timer_fd=timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0)
-	{
-		mylog(log_fatal,"timer_fd create error\n");
-		myexit(1);
-	}
-	its.it_interval.tv_sec=(timer_interval/1000);
-	its.it_interval.tv_nsec=(timer_interval%1000)*1000ll*1000ll;
-	its.it_value.tv_nsec=1; //imidiately
-	timerfd_settime(timer_fd,0,&its,0);
-
-
-	ev.events = EPOLLIN;
-	ev.data.u64 = pack_u64(2,timer_fd);////difference
-
-	ret=epoll_ctl(epollfd, EPOLL_CTL_ADD, timer_fd, &ev);
-	if (ret < 0) {
-		mylog(log_fatal,"epoll_ctl return %d\n", ret);
-		myexit(-1);
-	}
-	return 0;
-}
 int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is ready in epoll
 {
 	//keep_iptables_rule();
@@ -637,35 +508,7 @@ int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a p
 	}
 	return 0;
 }
-int handle_lower_level(raw_info_t &raw_info)//fill lower_level info,when --lower-level is enabled,only for server
-{
-	packet_info_t &send_info=raw_info.send_info;
-	packet_info_t &recv_info=raw_info.recv_info;
 
-	if(lower_level_manual)
-	{
-		memset(&send_info.addr_ll,0,sizeof(send_info.addr_ll));
-		send_info.addr_ll.sll_family=AF_PACKET;
-		send_info.addr_ll.sll_ifindex=ifindex;
-		send_info.addr_ll.sll_halen=ETHER_ADDR_LEN;
-		send_info.addr_ll.sll_protocol=htons(ETH_P_IP);
-		memcpy(&send_info.addr_ll.sll_addr,dest_hw_addr,ETHER_ADDR_LEN);
-		 mylog(log_debug,"[manual]lower level info %x %x\n ",send_info.addr_ll.sll_halen,send_info.addr_ll.sll_protocol);
-	}
-	else
-	{
-	memset(&send_info.addr_ll,0,sizeof(send_info.addr_ll));
-	send_info.addr_ll.sll_family=recv_info.addr_ll.sll_family;
-	send_info.addr_ll.sll_ifindex=recv_info.addr_ll.sll_ifindex;
-	send_info.addr_ll.sll_protocol=recv_info.addr_ll.sll_protocol;
-	send_info.addr_ll.sll_halen=recv_info.addr_ll.sll_halen;
-	memcpy(send_info.addr_ll.sll_addr,recv_info.addr_ll.sll_addr,sizeof(send_info.addr_ll.sll_addr));
-	//other bytes should be kept zero.
-
-	  mylog(log_debug,"[auto]lower level info %x %x\n ",send_info.addr_ll.sll_halen,send_info.addr_ll.sll_protocol);
-	}
-	return 0;
-}
 int server_on_raw_recv_multi() //called when server received an raw packet
 {
 	char dummy_buf[buf_len];
@@ -1689,840 +1532,11 @@ int server_event_loop()
 	}
 	return 0;
 }
-//char lower_level_arg[1000];
-int process_lower_level_arg()//handle --lower-level option
-{
-	lower_level=1;
-	if(strcmp(optarg,"auto")==0)
-	{
-		return 0;
-	}
-
-	lower_level_manual=1;
-	if (strchr(optarg, '#') == 0) {
-		mylog(log_fatal,
-				"lower-level parameter invaild,check help page for format\n");
-		myexit(-1);
-	}
-	lower_level = 1;
-	u32_t hw[6];
-	memset(hw, 0, sizeof(hw));
-	sscanf(optarg, "%[^#]#%x:%x:%x:%x:%x:%x", if_name, &hw[0], &hw[1], &hw[2],
-			&hw[3], &hw[4], &hw[5]);
-
-	mylog(log_warn,
-			"make sure this is correct:   if_name=<%s>  dest_mac_adress=<%02x:%02x:%02x:%02x:%02x:%02x>  \n",
-			if_name, hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);
-	for (int i = 0; i < 6; i++) {
-		dest_hw_addr[i] = uint8_t(hw[i]);
-	}
-	return 0;
-}
-void print_help()
-{
-	char git_version_buf[100]={0};
-	strncpy(git_version_buf,gitversion,10);
-	printf("udp2raw-tunnel\n");
-	printf("git version:%s    ",git_version_buf);
-	printf("build date:%s %s\n",__DATE__,__TIME__);
-
-	printf("repository: https://github.com/wangyu-/udp2raw-tunnel\n");
-	printf("\n");
-	printf("usage:\n");
-	printf("    run as client : ./this_program -c -l local_listen_ip:local_port -r server_ip:server_port  [options]\n");
-	printf("    run as server : ./this_program -s -l server_listen_ip:server_port -r remote_ip:remote_port  [options]\n");
-	printf("\n");
-	printf("common options,these options must be same on both side:\n");
-	printf("    --raw-mode            <string>        avaliable values:faketcp(default),udp,icmp\n");
-	printf("    -k,--key              <string>        password to gen symetric key,default:\"secret key\"\n");
-	printf("    --cipher-mode         <string>        avaliable values:aes128cbc(default),xor,none\n");
-	printf("    --auth-mode           <string>        avaliable values:md5(default),crc32,simple,none\n");
-	printf("    -a,--auto-rule                        auto add (and delete) iptables rule\n");
-	printf("    -g,--gen-rule                         generate iptables rule then exit,so that you can copy and\n");
-	printf("                                          add it manually.overrides -a\n");
-	printf("    --disable-anti-replay                 disable anti-replay,not suggested\n");
-
-	//printf("\n");
-	printf("client options:\n");
-	printf("    --source-ip           <ip>            force source-ip for raw socket\n");
-	printf("    --source-port         <port>          force source-port for raw socket,tcp/udp only\n");
-	printf("                                          this option disables port changing while re-connecting\n");
-//	printf("                                          \n");
-	printf("other options:\n");
-	printf("    --conf-file           <string>        read options from a configuration file instead of command line.\n");
-	printf("                                          check example.conf in repo for format\n");
-	printf("    --log-level           <number>        0:never    1:fatal   2:error   3:warn \n");
-	printf("                                          4:info (default)     5:debug   6:trace\n");
-//	printf("\n");
-	printf("    --log-position                        enable file name,function name,line number in log\n");
-	printf("    --disable-color                       disable log color\n");
-	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");
-	printf("    --sock-buf            <number>        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            <number>        seq increase mode for faketcp:\n");
-	printf("                                          0:static header,do not increase seq and ack_seq\n");
-	printf("                                          1:increase seq for every packet,simply ack last seq\n");
-	printf("                                          2:increase seq randomly, about every 3 packets,simply ack last seq\n");
-	printf("                                          3:simulate an almost real seq/ack procedure(default)\n");
-	printf("                                          4:similiar to 3,but do not consider TCP Option Window_Scale,\n");
-	printf("                                          maybe useful when firewall doesnt support TCP Option \n");
-//	printf("\n");
-	printf("    --lower-level         <string>        send packets at OSI level 2, format:'if_name#dest_mac_adress'\n");
-	printf("                                          ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain\n");
-	printf("                                          the parameter automatically,specify it manually if 'auto' failed\n");
-	printf("    --gen-add                             generate iptables rule and add it permanently,then exit.overrides -g\n");
-	printf("    --keep-rule                           monitor iptables and auto re-add if necessary.implys -a\n");
-	printf("    --clear                               clear any iptables rules added by this program.overrides everything\n");
-	printf("    -h,--help                             print this help message\n");
-
-	//printf("common options,these options must be same on both side\n");
-}
-
-int load_config(char *file_name, int &argc, vector<string> &argv) //load conf file and append to argv
-{
-	// Load configurations from config_file instead of the command line.
-	// See config.example for example configurations
-	std::ifstream conf_file(file_name);
-	std::string line;
-	if(conf_file.fail())
-	{
-		mylog(log_fatal,"conf_file %s open failed,reason :%s\n",file_name,strerror(errno));
-		myexit(-1);
-	}
-	while(std::getline(conf_file,line))
-	{
-		auto res=parse_conf_line(line);
-
-		argc+=res.size();
-		for(int i=0;i<(int)res.size();i++)
-		{
-			argv.push_back(res[i]);
-		}
-	}
-	conf_file.close();
-
-	return 0;
-}
-
-int unit_test()
-{
-	printf("running unit test\n");
-	vector<string> conf_lines= {"---aaa","--aaa bbb","-a bbb"," \t \t \t-a\t \t \t bbbbb\t \t \t "};
-	for(int i=0;i<int(conf_lines.size());i++)
-	{
-		printf("orign:%s\n",conf_lines[i].c_str());
-		auto res=parse_conf_line(conf_lines[i]);
-		printf("pasrse_result: size %d",int(res.size()));
-		for(int j=0;j<int(res.size());j++)
-		{
-			printf("<%s>",res[j].c_str());
-		}
-		printf("\n");
-	}
 
-	char s1[]={1,2,3,4,5};
 
-	char s2[]={1};
 
-	short c1=csum((unsigned short*)s1,5);
-	short c2=csum((unsigned short*)s2,1);
-	//c2=0;
 
-	printf("%x %x\n",(int)c1,(int)c2);
 
-	const char buf[]={1,2,3,4,5,6,7,8,9,10,11,2,13,14,15,16};
-	char key[100]={0};
-	char buf2[100]={0};
-	char buf3[100]={0};
-	char buf4[100]={0};
-	int len=16;
-	for(int i=0;i<len;i++)
-	{
-		printf("<%d>",buf[i]);
-	}
-	printf("\n");
-	cipher_encrypt(buf,buf2,len,key);
-	for(int i=0;i<len;i++)
-	{
-		printf("<%d>",buf2[i]);
-	}
-	printf("\n");
-	int temp_len=len;
-	cipher_decrypt(buf2,buf3,len,key);
-	for(int i=0;i<len;i++)
-	{
-		printf("<%d>",buf3[i]);
-	}
-	printf("\n");
-	cipher_encrypt(buf2,buf4,temp_len,key);
-	for(int i=0;i<temp_len;i++)
-	{
-		printf("<%d>",buf4[i]);
-	}
-	return 0;
-}
-
-int process_log_level(int argc,char *argv[])//process  --log-level and --disable-cloer --log-postion options
-{
-	int i,j,k;
-	for (i = 0; i < argc; i++)
-	{
-		if(strcmp(argv[i],"--log-level")==0)
-		{
-			if(i<argc -1)
-			{
-				sscanf(argv[i+1],"%d",&log_level);
-				if(0<=log_level&&log_level<log_end)
-				{
-				}
-				else
-				{
-					log_bare(log_fatal,"invalid log_level\n");
-					myexit(-1);
-				}
-			}
-		}
-		if(strcmp(argv[i],"--disable-color")==0)
-		{
-			enable_log_color=0;
-		}
-		if(strcmp(argv[i],"--log-position")==0)
-		{
-			enable_log_position=1;
-		}
-	}
-	return 0;
-}
-void process_arg(int argc, char *argv[])  //process all options
-{
-	int i,j,k,opt;
-
-	int option_index = 0;
-
-	char options[]="l:r:schk:ag";
-	static struct option long_options[] =
-	  {
-	    /* These options set a flag. */
-	    {"source-ip", required_argument,    0, 1},
-	    {"source-port", required_argument,    0, 1},
-		{"log-level", required_argument,    0, 1},
-		{"key", required_argument,    0, 'k'},
-		{"auth-mode", required_argument,    0, 1},
-		{"cipher-mode", required_argument,    0, 1},
-		{"raw-mode", required_argument,    0, 1},
-		{"disable-color", no_argument,    0, 1},
-		{"log-position", no_argument,    0, 1},
-		{"disable-bpf", no_argument,    0, 1},
-		{"disable-anti-replay", no_argument,    0, 1},
-		{"auto-rule", no_argument,    0, 'a'},
-		{"gen-rule", no_argument,    0, 'g'},
-		{"gen-add", no_argument,    0, 1},
-		{"debug", no_argument,    0, 1},
-		{"clear", no_argument,    0, 1},
-		{"simple-rule", no_argument,    0, 1},
-		{"keep-rule", no_argument,    0, 1},
-		{"lower-level", required_argument,    0, 1},
-		{"sock-buf", required_argument,    0, 1},
-		{"seq-mode", required_argument,    0, 1},
-		{"conf-file", required_argument,   0, 1},
-		{"force-sock-buf", no_argument,   0, 1},
-		{NULL, 0, 0, 0}
-	  };
-
-   process_log_level(argc,argv);
-
-   set<string> all_options;
-   map<string,string> shortcut_map;
-
-   all_options.insert("--help");
-   all_options.insert("-h");
-   string dummy="";
-   for(i=0;i<(int)strlen(options);i++)
-   {
-
-	   char val=options[i];
-	   if( ( val>='0'&&val<='9') ||( val>='a'&&val<='z')||(val>='A'&&val<='Z'))
-	   {
-		   all_options.insert(dummy+'-'+val);
-	   }
-   }
-   for(i=0;i<int(       sizeof(long_options)/sizeof(long_options[0])      );i++)
-   {
-	   if(long_options[i].name==NULL) break;
-	   int val=long_options[i].val;
-	   if( ( val>='0'&&val<='9') ||( val>='a'&&val<='z')||(val>='A'&&val<='Z'))
-	   {
-		   shortcut_map[dummy+"--"+long_options[i].name]= dummy+"-"+ char(val);
-	   }
-	  all_options.insert(dummy+"--"+long_options[i].name);
-   }
-
-	for (i = 0; i < argc; i++)
-	{
-		int len=strlen(argv[i]);
-		if(len==0)
-		{
-			mylog(log_fatal,"found an empty string in options\n");
-			myexit(-1);
-		}
-		if(len==1&&argv[i][0]=='-' )
-		{
-			mylog(log_fatal,"invaild option '-' in argv\n");
-			myexit(-1);
-		}
-		if(len==2&&argv[i][0]=='-'&&argv[i][1]=='-' )
-		{
-			mylog(log_fatal,"invaild option '--' in argv\n");
-			myexit(-1);
-		}
-	}
-
-   mylog(log_info,"argc=%d ", argc);
-
-	for (i = 0; i < argc; i++) {
-		log_bare(log_info, "%s ", argv[i]);
-	}
-	log_bare(log_info, "\n");
-
-	//string dummy="";
-   for(i=+1;i<argc;i++)
-   {
-	   if(argv[i][0]!='-') continue;
-	   string a=argv[i];
-	   if(a[0]=='-'&&a[1]!='-')
-		   a=dummy+a[0]+a[1];
-
-	   if(all_options.find(a.c_str())==all_options.end())
-	   {
-			mylog(log_fatal,"invaild option %s\n",a.c_str());
-			myexit(-1);
-	   }
-	   for(j=i+1;j<argc;j++)
-	   {
-		   if(argv[j][0]!='-') continue;
-
-		   string b=argv[j];
-
-		   if(b[0]=='-'&&b[1]!='-')
-			   b=dummy+b[0]+b[1];
-
-		   if(shortcut_map.find(a)!=shortcut_map.end())
-				   a=shortcut_map[a];
-		   if(shortcut_map.find(b)!=shortcut_map.end())
-				   b=shortcut_map[b];
-		   if(a==b)
-		   {
-				mylog(log_fatal,"%s duplicates with %s\n",argv[i],argv[j]);
-				myexit(-1);
-		   }
-	   }
-   }
-
-
-
-
-
-	int no_l = 1, no_r = 1;
-	while ((opt = getopt_long(argc, argv,options,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_ip, &local_port);
-				if(local_port==22)
-				{
-					mylog(log_fatal,"port 22 not allowed\n");
-					myexit(-1);
-				}
-			} else {
-				mylog(log_fatal,"invalid parameter for -l ,%s,should be ip:port\n",optarg);
-				myexit(-1);
-
-			}
-			break;
-		case 'r':
-			no_r = 0;
-			if (strchr(optarg, ':') != 0) {
-				sscanf(optarg, "%[^:]:%d", remote_ip, &remote_port);
-				if(remote_port==22)
-				{
-					mylog(log_fatal,"port 22 not allowed\n");
-					myexit(-1);
-				}
-			} else {
-				mylog(log_fatal,"invalid parameter for -r ,%s,should be ip:port\n",optarg);
-				myexit(-1);
-			}
-			break;
-		case 's':
-			if(program_mode==0)
-			{
-				program_mode=server_mode;
-			}
-			else
-			{
-				mylog(log_fatal,"-s /-c has already been set,conflict\n");
-				myexit(-1);
-			}
-			break;
-		case 'c':
-			if(program_mode==0)
-			{
-				program_mode=client_mode;
-			}
-			else
-			{
-				mylog(log_fatal,"-s /-c has already been set,conflict\n");
-				myexit(-1);
-			}
-			break;
-		case 'h':
-			break;
-		case 'a':
-			auto_add_iptables_rule=1;
-			break;
-		case 'g':
-			generate_iptables_rule=1;
-			break;
-		case 'k':
-			mylog(log_debug,"parsing key option\n");
-			sscanf(optarg,"%s",key_string);
-			break;
-		case 1:
-			mylog(log_debug,"option_index: %d\n",option_index);
-			if(strcmp(long_options[option_index].name,"clear")==0)
-			{
-				char *output;
-				//int ret =system("iptables-save |grep udp2raw_dWRwMnJhdw|sed -n 's/^-A/iptables -D/p'|sh");
-				int ret =run_command("iptables -S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-A/iptables -D/p'|sh",output);
-
-				int ret2 =run_command("iptables -S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-N/iptables -X/p'|sh",output);
-				//system("iptables-save |grep udp2raw_dWRwMnJhdw|sed 's/^-A/iptables -D/'|sh");
-				//system("iptables-save|grep -v udp2raw_dWRwMnJhdw|iptables-restore");
-				mylog(log_info,"tried to clear all iptables rule created previously,return value %d %d\n",ret,ret2);
-				myexit(-1);
-			}
-			else if(strcmp(long_options[option_index].name,"source-ip")==0)
-			{
-				mylog(log_debug,"parsing long option :source-ip\n");
-				sscanf(optarg, "%s", source_ip);
-				mylog(log_debug,"source: %s\n",source_ip);
-				force_source_ip=1;
-			}
-			else if(strcmp(long_options[option_index].name,"source-port")==0)
-			{
-				mylog(log_debug,"parsing long option :source-port\n");
-				sscanf(optarg, "%d", &source_port);
-				mylog(log_info,"source: %d\n",source_port);
-			}
-			else if(strcmp(long_options[option_index].name,"raw-mode")==0)
-			{
-				for(i=0;i<mode_end;i++)
-				{
-					if(strcmp(optarg,raw_mode_tostring[i])==0)
-					{
-						//printf("%d i\n",i);
-						//printf("%s",raw_mode_tostring[i]);
-						raw_mode=(raw_mode_t)i;
-						break;
-					}
-				}
-				if(i==mode_end)
-				{
-					mylog(log_fatal,"no such raw_mode %s\n",optarg);
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"auth-mode")==0)
-			{
-				for(i=0;i<auth_end;i++)
-				{
-					if(strcmp(optarg,auth_mode_tostring[i])==0)
-					{
-						auth_mode=(auth_mode_t)i;
-						if(auth_mode==auth_none)
-						{
-							disable_anti_replay=1;
-						}
-						break;
-					}
-				}
-				if(i==auth_end)
-				{
-					mylog(log_fatal,"no such auth_mode %s\n",optarg);
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"cipher-mode")==0)
-			{
-				for(i=0;i<cipher_end;i++)
-				{
-					if(strcmp(optarg,cipher_mode_tostring[i])==0)
-					{
-						cipher_mode=(cipher_mode_t)i;
-						break;
-					}
-				}
-				if(i==cipher_end)
-				{
-
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"log-level")==0)
-			{
-			}
-			else if(strcmp(long_options[option_index].name,"lower-level")==0)
-			{
-				process_lower_level_arg();
-				//lower_level=1;
-				//strcpy(lower_level_arg,optarg);
-			}
-			else if(strcmp(long_options[option_index].name,"simple-rule")==0)
-			{
-				simple_rule=1;
-			}
-			else if(strcmp(long_options[option_index].name,"keep-rule")==0)
-			{
-				keep_rule=1;
-			}
-			else if(strcmp(long_options[option_index].name,"gen-add")==0)
-			{
-				generate_iptables_rule_add=1;
-			}
-			else if(strcmp(long_options[option_index].name,"disable-color")==0)
-			{
-				//enable_log_color=0;
-			}
-			else if(strcmp(long_options[option_index].name,"debug")==0)
-			{
-				debug_flag=1;
-				//enable_log_color=0;
-			}
-			else if(strcmp(long_options[option_index].name,"debug-resend")==0)
-			{
-				//debug_resend=1;
-				//enable_log_color=0;
-			}
-			else if(strcmp(long_options[option_index].name,"log-position")==0)
-			{
-				//enable_log_position=1;
-			}
-			else if(strcmp(long_options[option_index].name,"force-sock-buf")==0)
-			{
-				force_socket_buf=1;
-			}
-			else if(strcmp(long_options[option_index].name,"disable-bpf")==0)
-			{
-				disable_bpf_filter=1;
-			}
-			else if(strcmp(long_options[option_index].name,"disable-anti-replay")==0)
-			{
-				disable_anti_replay=1;
-			}
-			else if(strcmp(long_options[option_index].name,"sock-buf")==0)
-			{
-				int tmp=-1;
-				sscanf(optarg,"%d",&tmp);
-				if(10<=tmp&&tmp<=10*1024)
-				{
-					socket_buf_size=tmp*1024;
-				}
-				else
-				{
-					mylog(log_fatal,"sock-buf value must be between 1 and 10240 (kbyte) \n");
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"seq-mode")==0)
-			{
-				sscanf(optarg,"%d",&seq_mode);
-				if(0<=seq_mode&&seq_mode<=max_seq_mode)
-				{
-				}
-				else
-				{
-					mylog(log_fatal,"seq_mode value must be  0,1,or 2 \n");
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"conf-file")==0)
-			{
-				mylog(log_info,"configuration loaded from %s\n",optarg);
-			}
-			else
-			{
-				mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt);
-			}
-			break;
-		default:
-			mylog(log_fatal,"unknown option ,code:<%c>,<%x>\n",optopt, optopt);
-			myexit(-1);
-		}
-	}
-
-	if (no_l)
-		mylog(log_fatal,"error: -l not found\n");
-	if (no_r)
-		mylog(log_fatal,"error: -r not found\n");
-	if(program_mode==0)
-		mylog(log_fatal,"error: -c /-s  hasnt been set\n");
-	if (no_l || no_r||program_mode==0)
-	{
-		print_help();
-		myexit(-1);
-	}
-	//if(lower_level)
-		//process_lower_level_arg();
-
-	 mylog(log_info,"important variables: ");
-
-	 log_bare(log_info,"log_level=%d:%s ",log_level,log_text[log_level]);
-	 log_bare(log_info,"raw_mode=%s ",raw_mode_tostring[raw_mode]);
-	 log_bare(log_info,"cipher_mode=%s ",cipher_mode_tostring[cipher_mode]);
-	 log_bare(log_info,"auth_mode=%s ",auth_mode_tostring[auth_mode]);
-
-	 log_bare(log_info,"key=%s ",key_string);
-
-	 log_bare(log_info,"local_ip=%s ",local_ip);
-	 log_bare(log_info,"local_port=%d ",local_port);
-	 log_bare(log_info,"remote_ip=%s ",remote_ip);
-	 log_bare(log_info,"remote_port=%d ",remote_port);
-	 log_bare(log_info,"source_ip=%s ",source_ip);
-	 log_bare(log_info,"source_port=%d ",source_port);
-
-	 log_bare(log_info,"socket_buf_size=%d ",socket_buf_size);
-
-	 log_bare(log_info,"\n");
-}
-void pre_process_arg(int argc, char *argv[])//mainly for load conf file
-{
-	int i,j,k;
-	for (i = 0; i < argc; i++)
-	{
-		if(strcmp(argv[i],"--unit-test")==0)
-		{
-			unit_test();
-			myexit(0);
-		}
-
-	}
-
-	for (i = 0; i < argc; i++)
-	{
-		if(strcmp(argv[i],"-h")==0||strcmp(argv[i],"--help")==0)
-		{
-			print_help();
-			myexit(0);
-		}
-
-	}
-
-	if (argc == 1)
-	{
-		print_help();
-		myexit(-1);
-	}
-
-	process_log_level(argc,argv);
-
-	int new_argc=0;
-	vector<string> new_argv;
-
-	int count=0;
-	int pos=-1;
-
-	for (i = 0; i < argc; i++)
-	{
-		if(strcmp(argv[i],"--conf-file")==0)
-		{
-			count++;
-			pos=i;
-			if(i==argc)
-			{
-				mylog(log_fatal,"--conf-file need a parameter\n");
-				myexit(-1);
-			}
-			if(argv[i+1][0]=='-')
-			{
-				mylog(log_fatal,"--conf-file need a parameter\n");
-				myexit(-1);
-			}
-			i++;
-		}
-		else
-		{
-			//printf("<%s>",argv[i]);
-			new_argc++;
-			new_argv.push_back(argv[i]);
-		}
-	}
-	if(count>1)
-	{
-		mylog(log_fatal,"duplicated --conf-file option\n");
-		myexit(-1);
-	}
-
-	if(count>0)
-	{
-		load_config(argv[pos+1],new_argc,new_argv);
-	}
-	char* new_argv_char[new_argv.size()];
-
-	new_argc=0;
-	for(i=0;i<(int)new_argv.size();i++)
-	{
-		if(strcmp(new_argv[i].c_str(),"--conf-file")==0)
-		{
-			mylog(log_fatal,"cant have --conf-file in a config file\n");
-			myexit(-1);
-		}
-		new_argv_char[new_argc++]=(char *)new_argv[i].c_str();
-	}
-	process_arg(new_argc,new_argv_char);
-
-}
-void *run_keep(void *none)  //called in a new thread for --keep-rule option
-{
-
-	while(1)
-	{
-		sleep(iptables_rule_keep_interval);
-		keep_iptables_rule();
-		if(about_to_exit)   //just incase it runs forever if there is some bug,not necessary
-		{
-			sleep(10);
-			keep_thread_running=0; //not thread safe ,but wont cause problem
-			break;
-		}
-	}
-	return NULL;
-
-}
-void iptables_rule()  // handles -a -g --gen-add  --keep-rule
-{
-	if(auto_add_iptables_rule&&generate_iptables_rule)
-	{
-		mylog(log_warn," -g overrides -a\n");
-		auto_add_iptables_rule=0;
-		//myexit(-1);
-	}
-	if(generate_iptables_rule_add&&generate_iptables_rule)
-	{
-		mylog(log_warn," --gen-add overrides -g\n");
-		generate_iptables_rule=0;
-		//myexit(-1);
-	}
-
-	if(keep_rule&&auto_add_iptables_rule==0)
-	{
-		auto_add_iptables_rule=1;
-		mylog(log_warn," --keep_rule implys -a\n");
-		generate_iptables_rule=0;
-		//myexit(-1);
-	}
-	char tmp_pattern[200];
-	string pattern="";
-
-	if(program_mode==client_mode)
-	{
-		if(raw_mode==mode_faketcp)
-		{
-			sprintf(tmp_pattern,"-s %s/32 -p tcp -m tcp --sport %d",remote_ip,remote_port);
-		}
-		if(raw_mode==mode_udp)
-		{
-			sprintf(tmp_pattern,"-s %s/32 -p udp -m udp --sport %d",remote_ip,remote_port);
-		}
-		if(raw_mode==mode_icmp)
-		{
-			sprintf(tmp_pattern,"-s %s/32 -p icmp",remote_ip);
-		}
-		pattern=tmp_pattern;
-	}
-	if(program_mode==server_mode)
-	{
-
-		if(raw_mode==mode_faketcp)
-		{
-			sprintf(tmp_pattern,"-p tcp -m tcp --dport %d",local_port);
-		}
-		if(raw_mode==mode_udp)
-		{
-			sprintf(tmp_pattern,"-p udp -m udp --dport %d",local_port);
-		}
-		if(raw_mode==mode_icmp)
-		{
-			if(local_ip_uint32==0)
-			{
-				sprintf(tmp_pattern,"-p icmp");
-			}
-			else
-			{
-				sprintf(tmp_pattern,"-d %s/32 -p icmp",local_ip);
-			}
-		}
-		pattern=tmp_pattern;
-	}
-/*
-	if(!simple_rule)
-	{
-		pattern += " -m comment --comment udp2rawDwrW_";
-
-		char const_id_str[100];
-		sprintf(const_id_str, "%x_", const_id);
-
-		pattern += const_id_str;
-
-		time_t timer;
-		char buffer[26];
-		struct tm* tm_info;
-
-		time(&timer);
-		tm_info = localtime(&timer);
-
-		strftime(buffer, 26, "%Y-%m-%d-%H:%M:%S", tm_info);
-
-		pattern += buffer;
-
-
-	}*/
-
-	if(auto_add_iptables_rule)
-	{
-		iptables_rule_init(pattern.c_str(),const_id,keep_rule);
-		if(keep_rule)
-		{
-			if(pthread_create(&keep_thread, NULL, run_keep, 0)) {
-
-				mylog(log_fatal, "Error creating thread\n");
-				myexit(-1);
-			}
-			keep_thread_running=1;
-		}
-	}
-	if(generate_iptables_rule)
-	{
-		string rule="iptables -I INPUT ";
-		rule+=pattern;
-		rule+=" -j DROP";
-
-		printf("generated iptables rule:\n");
-		printf("%s\n",rule.c_str());
-		myexit(0);
-	}
-	if(generate_iptables_rule_add)
-	{
-		iptables_gen_add(pattern.c_str(),const_id);
-		myexit(0);
-	}
-
-
-}
 
 /*
 int test()

+ 1 - 1
makefile

@@ -8,7 +8,7 @@ cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
 #cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ 
 FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers
 
-COMMON=main.cpp lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp  connection.cpp -lpthread
+COMMON=main.cpp lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp  connection.cpp misc.cpp -lpthread
 SOURCES= $(COMMON) lib/aes_faster_c/aes.c lib/aes_faster_c/wrapper.c
 SOURCES_TINY_AES= $(COMMON) lib/aes.c
 SOURCES_AES_ACC=$(COMMON) $(wildcard lib/aes_acc/aes*.c)

+ 976 - 0
misc.cpp

@@ -0,0 +1,976 @@
+/*
+ * misc.cpp
+ *
+ *  Created on: Sep 23, 2017
+ *      Author: root
+ */
+#include "git_version.h"
+#include "common.h"
+#include "encrypt.h"
+#include "misc.h"
+#include "network.h"
+#include "connection.h"
+
+
+char local_ip[100]="0.0.0.0", remote_ip[100]="255.255.255.255",source_ip[100]="0.0.0.0";//local_ip is for -l option,remote_ip for -r option,source for --source-ip
+u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.
+int local_port = -1, remote_port=-1,source_port=0;//similiar to local_ip  remote_ip,buf for port.source_port=0 indicates --source-port is not enabled
+
+int force_source_ip=0; //if --source-ip is enabled
+
+
+id_t const_id=0;//an id used for connection recovery,its generated randomly,it never change since its generated
+
+
+
+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
+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.
+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
+
+
+int simple_rule=0;  //deprecated.
+int keep_rule=0; //whether to monitor the iptables rule periodly,re-add if losted
+int auto_add_iptables_rule=0;//if -a is set
+int generate_iptables_rule=0;//if -g is set
+int generate_iptables_rule_add=0;// if --gen-add is set
+
+int debug_resend=0; // debug only
+
+char key_string[1000]= "secret key";// -k option
+
+
+
+//char lower_level_arg[1000];
+int process_lower_level_arg()//handle --lower-level option
+{
+	lower_level=1;
+	if(strcmp(optarg,"auto")==0)
+	{
+		return 0;
+	}
+
+	lower_level_manual=1;
+	if (strchr(optarg, '#') == 0) {
+		mylog(log_fatal,
+				"lower-level parameter invaild,check help page for format\n");
+		myexit(-1);
+	}
+	lower_level = 1;
+	u32_t hw[6];
+	memset(hw, 0, sizeof(hw));
+	sscanf(optarg, "%[^#]#%x:%x:%x:%x:%x:%x", if_name, &hw[0], &hw[1], &hw[2],
+			&hw[3], &hw[4], &hw[5]);
+
+	mylog(log_warn,
+			"make sure this is correct:   if_name=<%s>  dest_mac_adress=<%02x:%02x:%02x:%02x:%02x:%02x>  \n",
+			if_name, hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);
+	for (int i = 0; i < 6; i++) {
+		dest_hw_addr[i] = uint8_t(hw[i]);
+	}
+	return 0;
+}
+void print_help()
+{
+	char git_version_buf[100]={0};
+	strncpy(git_version_buf,gitversion,10);
+	printf("udp2raw-tunnel\n");
+	printf("git version:%s    ",git_version_buf);
+	printf("build date:%s %s\n",__DATE__,__TIME__);
+
+	printf("repository: https://github.com/wangyu-/udp2raw-tunnel\n");
+	printf("\n");
+	printf("usage:\n");
+	printf("    run as client : ./this_program -c -l local_listen_ip:local_port -r server_ip:server_port  [options]\n");
+	printf("    run as server : ./this_program -s -l server_listen_ip:server_port -r remote_ip:remote_port  [options]\n");
+	printf("\n");
+	printf("common options,these options must be same on both side:\n");
+	printf("    --raw-mode            <string>        avaliable values:faketcp(default),udp,icmp\n");
+	printf("    -k,--key              <string>        password to gen symetric key,default:\"secret key\"\n");
+	printf("    --cipher-mode         <string>        avaliable values:aes128cbc(default),xor,none\n");
+	printf("    --auth-mode           <string>        avaliable values:md5(default),crc32,simple,none\n");
+	printf("    -a,--auto-rule                        auto add (and delete) iptables rule\n");
+	printf("    -g,--gen-rule                         generate iptables rule then exit,so that you can copy and\n");
+	printf("                                          add it manually.overrides -a\n");
+	printf("    --disable-anti-replay                 disable anti-replay,not suggested\n");
+
+	//printf("\n");
+	printf("client options:\n");
+	printf("    --source-ip           <ip>            force source-ip for raw socket\n");
+	printf("    --source-port         <port>          force source-port for raw socket,tcp/udp only\n");
+	printf("                                          this option disables port changing while re-connecting\n");
+//	printf("                                          \n");
+	printf("other options:\n");
+	printf("    --conf-file           <string>        read options from a configuration file instead of command line.\n");
+	printf("                                          check example.conf in repo for format\n");
+	printf("    --log-level           <number>        0:never    1:fatal   2:error   3:warn \n");
+	printf("                                          4:info (default)     5:debug   6:trace\n");
+//	printf("\n");
+	printf("    --log-position                        enable file name,function name,line number in log\n");
+	printf("    --disable-color                       disable log color\n");
+	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");
+	printf("    --sock-buf            <number>        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            <number>        seq increase mode for faketcp:\n");
+	printf("                                          0:static header,do not increase seq and ack_seq\n");
+	printf("                                          1:increase seq for every packet,simply ack last seq\n");
+	printf("                                          2:increase seq randomly, about every 3 packets,simply ack last seq\n");
+	printf("                                          3:simulate an almost real seq/ack procedure(default)\n");
+	printf("                                          4:similiar to 3,but do not consider TCP Option Window_Scale,\n");
+	printf("                                          maybe useful when firewall doesnt support TCP Option \n");
+//	printf("\n");
+	printf("    --lower-level         <string>        send packets at OSI level 2, format:'if_name#dest_mac_adress'\n");
+	printf("                                          ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain\n");
+	printf("                                          the parameter automatically,specify it manually if 'auto' failed\n");
+	printf("    --gen-add                             generate iptables rule and add it permanently,then exit.overrides -g\n");
+	printf("    --keep-rule                           monitor iptables and auto re-add if necessary.implys -a\n");
+	printf("    --clear                               clear any iptables rules added by this program.overrides everything\n");
+	printf("    -h,--help                             print this help message\n");
+
+	//printf("common options,these options must be same on both side\n");
+}
+
+int load_config(char *file_name, int &argc, vector<string> &argv) //load conf file and append to argv
+{
+	// Load configurations from config_file instead of the command line.
+	// See config.example for example configurations
+	std::ifstream conf_file(file_name);
+	std::string line;
+	if(conf_file.fail())
+	{
+		mylog(log_fatal,"conf_file %s open failed,reason :%s\n",file_name,strerror(errno));
+		myexit(-1);
+	}
+	while(std::getline(conf_file,line))
+	{
+		auto res=parse_conf_line(line);
+
+		argc+=res.size();
+		for(int i=0;i<(int)res.size();i++)
+		{
+			argv.push_back(res[i]);
+		}
+	}
+	conf_file.close();
+
+	return 0;
+}
+
+int process_log_level(int argc,char *argv[])//process  --log-level and --disable-cloer --log-postion options
+{
+	int i,j,k;
+	for (i = 0; i < argc; i++)
+	{
+		if(strcmp(argv[i],"--log-level")==0)
+		{
+			if(i<argc -1)
+			{
+				sscanf(argv[i+1],"%d",&log_level);
+				if(0<=log_level&&log_level<log_end)
+				{
+				}
+				else
+				{
+					log_bare(log_fatal,"invalid log_level\n");
+					myexit(-1);
+				}
+			}
+		}
+		if(strcmp(argv[i],"--disable-color")==0)
+		{
+			enable_log_color=0;
+		}
+		if(strcmp(argv[i],"--log-position")==0)
+		{
+			enable_log_position=1;
+		}
+	}
+	return 0;
+}
+void process_arg(int argc, char *argv[])  //process all options
+{
+	int i,j,k,opt;
+
+	int option_index = 0;
+
+	char options[]="l:r:schk:ag";
+	static struct option long_options[] =
+	  {
+	    /* These options set a flag. */
+	    {"source-ip", required_argument,    0, 1},
+	    {"source-port", required_argument,    0, 1},
+		{"log-level", required_argument,    0, 1},
+		{"key", required_argument,    0, 'k'},
+		{"auth-mode", required_argument,    0, 1},
+		{"cipher-mode", required_argument,    0, 1},
+		{"raw-mode", required_argument,    0, 1},
+		{"disable-color", no_argument,    0, 1},
+		{"log-position", no_argument,    0, 1},
+		{"disable-bpf", no_argument,    0, 1},
+		{"disable-anti-replay", no_argument,    0, 1},
+		{"auto-rule", no_argument,    0, 'a'},
+		{"gen-rule", no_argument,    0, 'g'},
+		{"gen-add", no_argument,    0, 1},
+		{"debug", no_argument,    0, 1},
+		{"clear", no_argument,    0, 1},
+		{"simple-rule", no_argument,    0, 1},
+		{"keep-rule", no_argument,    0, 1},
+		{"lower-level", required_argument,    0, 1},
+		{"sock-buf", required_argument,    0, 1},
+		{"seq-mode", required_argument,    0, 1},
+		{"conf-file", required_argument,   0, 1},
+		{"force-sock-buf", no_argument,   0, 1},
+		{NULL, 0, 0, 0}
+	  };
+
+   process_log_level(argc,argv);
+
+   set<string> all_options;
+   map<string,string> shortcut_map;
+
+   all_options.insert("--help");
+   all_options.insert("-h");
+   string dummy="";
+   for(i=0;i<(int)strlen(options);i++)
+   {
+
+	   char val=options[i];
+	   if( ( val>='0'&&val<='9') ||( val>='a'&&val<='z')||(val>='A'&&val<='Z'))
+	   {
+		   all_options.insert(dummy+'-'+val);
+	   }
+   }
+   for(i=0;i<int(       sizeof(long_options)/sizeof(long_options[0])      );i++)
+   {
+	   if(long_options[i].name==NULL) break;
+	   int val=long_options[i].val;
+	   if( ( val>='0'&&val<='9') ||( val>='a'&&val<='z')||(val>='A'&&val<='Z'))
+	   {
+		   shortcut_map[dummy+"--"+long_options[i].name]= dummy+"-"+ char(val);
+	   }
+	  all_options.insert(dummy+"--"+long_options[i].name);
+   }
+
+	for (i = 0; i < argc; i++)
+	{
+		int len=strlen(argv[i]);
+		if(len==0)
+		{
+			mylog(log_fatal,"found an empty string in options\n");
+			myexit(-1);
+		}
+		if(len==1&&argv[i][0]=='-' )
+		{
+			mylog(log_fatal,"invaild option '-' in argv\n");
+			myexit(-1);
+		}
+		if(len==2&&argv[i][0]=='-'&&argv[i][1]=='-' )
+		{
+			mylog(log_fatal,"invaild option '--' in argv\n");
+			myexit(-1);
+		}
+	}
+
+   mylog(log_info,"argc=%d ", argc);
+
+	for (i = 0; i < argc; i++) {
+		log_bare(log_info, "%s ", argv[i]);
+	}
+	log_bare(log_info, "\n");
+
+	//string dummy="";
+   for(i=+1;i<argc;i++)
+   {
+	   if(argv[i][0]!='-') continue;
+	   string a=argv[i];
+	   if(a[0]=='-'&&a[1]!='-')
+		   a=dummy+a[0]+a[1];
+
+	   if(all_options.find(a.c_str())==all_options.end())
+	   {
+			mylog(log_fatal,"invaild option %s\n",a.c_str());
+			myexit(-1);
+	   }
+	   for(j=i+1;j<argc;j++)
+	   {
+		   if(argv[j][0]!='-') continue;
+
+		   string b=argv[j];
+
+		   if(b[0]=='-'&&b[1]!='-')
+			   b=dummy+b[0]+b[1];
+
+		   if(shortcut_map.find(a)!=shortcut_map.end())
+				   a=shortcut_map[a];
+		   if(shortcut_map.find(b)!=shortcut_map.end())
+				   b=shortcut_map[b];
+		   if(a==b)
+		   {
+				mylog(log_fatal,"%s duplicates with %s\n",argv[i],argv[j]);
+				myexit(-1);
+		   }
+	   }
+   }
+
+
+
+
+
+	int no_l = 1, no_r = 1;
+	while ((opt = getopt_long(argc, argv,options,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_ip, &local_port);
+				if(local_port==22)
+				{
+					mylog(log_fatal,"port 22 not allowed\n");
+					myexit(-1);
+				}
+			} else {
+				mylog(log_fatal,"invalid parameter for -l ,%s,should be ip:port\n",optarg);
+				myexit(-1);
+
+			}
+			break;
+		case 'r':
+			no_r = 0;
+			if (strchr(optarg, ':') != 0) {
+				sscanf(optarg, "%[^:]:%d", remote_ip, &remote_port);
+				if(remote_port==22)
+				{
+					mylog(log_fatal,"port 22 not allowed\n");
+					myexit(-1);
+				}
+			} else {
+				mylog(log_fatal,"invalid parameter for -r ,%s,should be ip:port\n",optarg);
+				myexit(-1);
+			}
+			break;
+		case 's':
+			if(program_mode==0)
+			{
+				program_mode=server_mode;
+			}
+			else
+			{
+				mylog(log_fatal,"-s /-c has already been set,conflict\n");
+				myexit(-1);
+			}
+			break;
+		case 'c':
+			if(program_mode==0)
+			{
+				program_mode=client_mode;
+			}
+			else
+			{
+				mylog(log_fatal,"-s /-c has already been set,conflict\n");
+				myexit(-1);
+			}
+			break;
+		case 'h':
+			break;
+		case 'a':
+			auto_add_iptables_rule=1;
+			break;
+		case 'g':
+			generate_iptables_rule=1;
+			break;
+		case 'k':
+			mylog(log_debug,"parsing key option\n");
+			sscanf(optarg,"%s",key_string);
+			break;
+		case 1:
+			mylog(log_debug,"option_index: %d\n",option_index);
+			if(strcmp(long_options[option_index].name,"clear")==0)
+			{
+				char *output;
+				//int ret =system("iptables-save |grep udp2raw_dWRwMnJhdw|sed -n 's/^-A/iptables -D/p'|sh");
+				int ret =run_command("iptables -S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-A/iptables -D/p'|sh",output);
+
+				int ret2 =run_command("iptables -S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-N/iptables -X/p'|sh",output);
+				//system("iptables-save |grep udp2raw_dWRwMnJhdw|sed 's/^-A/iptables -D/'|sh");
+				//system("iptables-save|grep -v udp2raw_dWRwMnJhdw|iptables-restore");
+				mylog(log_info,"tried to clear all iptables rule created previously,return value %d %d\n",ret,ret2);
+				myexit(-1);
+			}
+			else if(strcmp(long_options[option_index].name,"source-ip")==0)
+			{
+				mylog(log_debug,"parsing long option :source-ip\n");
+				sscanf(optarg, "%s", source_ip);
+				mylog(log_debug,"source: %s\n",source_ip);
+				force_source_ip=1;
+			}
+			else if(strcmp(long_options[option_index].name,"source-port")==0)
+			{
+				mylog(log_debug,"parsing long option :source-port\n");
+				sscanf(optarg, "%d", &source_port);
+				mylog(log_info,"source: %d\n",source_port);
+			}
+			else if(strcmp(long_options[option_index].name,"raw-mode")==0)
+			{
+				for(i=0;i<mode_end;i++)
+				{
+					if(strcmp(optarg,raw_mode_tostring[i])==0)
+					{
+						//printf("%d i\n",i);
+						//printf("%s",raw_mode_tostring[i]);
+						raw_mode=(raw_mode_t)i;
+						break;
+					}
+				}
+				if(i==mode_end)
+				{
+					mylog(log_fatal,"no such raw_mode %s\n",optarg);
+					myexit(-1);
+				}
+			}
+			else if(strcmp(long_options[option_index].name,"auth-mode")==0)
+			{
+				for(i=0;i<auth_end;i++)
+				{
+					if(strcmp(optarg,auth_mode_tostring[i])==0)
+					{
+						auth_mode=(auth_mode_t)i;
+						if(auth_mode==auth_none)
+						{
+							disable_anti_replay=1;
+						}
+						break;
+					}
+				}
+				if(i==auth_end)
+				{
+					mylog(log_fatal,"no such auth_mode %s\n",optarg);
+					myexit(-1);
+				}
+			}
+			else if(strcmp(long_options[option_index].name,"cipher-mode")==0)
+			{
+				for(i=0;i<cipher_end;i++)
+				{
+					if(strcmp(optarg,cipher_mode_tostring[i])==0)
+					{
+						cipher_mode=(cipher_mode_t)i;
+						break;
+					}
+				}
+				if(i==cipher_end)
+				{
+
+					myexit(-1);
+				}
+			}
+			else if(strcmp(long_options[option_index].name,"log-level")==0)
+			{
+			}
+			else if(strcmp(long_options[option_index].name,"lower-level")==0)
+			{
+				process_lower_level_arg();
+				//lower_level=1;
+				//strcpy(lower_level_arg,optarg);
+			}
+			else if(strcmp(long_options[option_index].name,"simple-rule")==0)
+			{
+				simple_rule=1;
+			}
+			else if(strcmp(long_options[option_index].name,"keep-rule")==0)
+			{
+				keep_rule=1;
+			}
+			else if(strcmp(long_options[option_index].name,"gen-add")==0)
+			{
+				generate_iptables_rule_add=1;
+			}
+			else if(strcmp(long_options[option_index].name,"disable-color")==0)
+			{
+				//enable_log_color=0;
+			}
+			else if(strcmp(long_options[option_index].name,"debug")==0)
+			{
+				debug_flag=1;
+				//enable_log_color=0;
+			}
+			else if(strcmp(long_options[option_index].name,"debug-resend")==0)
+			{
+				//debug_resend=1;
+				//enable_log_color=0;
+			}
+			else if(strcmp(long_options[option_index].name,"log-position")==0)
+			{
+				//enable_log_position=1;
+			}
+			else if(strcmp(long_options[option_index].name,"force-sock-buf")==0)
+			{
+				force_socket_buf=1;
+			}
+			else if(strcmp(long_options[option_index].name,"disable-bpf")==0)
+			{
+				disable_bpf_filter=1;
+			}
+			else if(strcmp(long_options[option_index].name,"disable-anti-replay")==0)
+			{
+				disable_anti_replay=1;
+			}
+			else if(strcmp(long_options[option_index].name,"sock-buf")==0)
+			{
+				int tmp=-1;
+				sscanf(optarg,"%d",&tmp);
+				if(10<=tmp&&tmp<=10*1024)
+				{
+					socket_buf_size=tmp*1024;
+				}
+				else
+				{
+					mylog(log_fatal,"sock-buf value must be between 1 and 10240 (kbyte) \n");
+					myexit(-1);
+				}
+			}
+			else if(strcmp(long_options[option_index].name,"seq-mode")==0)
+			{
+				sscanf(optarg,"%d",&seq_mode);
+				if(0<=seq_mode&&seq_mode<=max_seq_mode)
+				{
+				}
+				else
+				{
+					mylog(log_fatal,"seq_mode value must be  0,1,or 2 \n");
+					myexit(-1);
+				}
+			}
+			else if(strcmp(long_options[option_index].name,"conf-file")==0)
+			{
+				mylog(log_info,"configuration loaded from %s\n",optarg);
+			}
+			else
+			{
+				mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt);
+			}
+			break;
+		default:
+			mylog(log_fatal,"unknown option ,code:<%c>,<%x>\n",optopt, optopt);
+			myexit(-1);
+		}
+	}
+
+	if (no_l)
+		mylog(log_fatal,"error: -l not found\n");
+	if (no_r)
+		mylog(log_fatal,"error: -r not found\n");
+	if(program_mode==0)
+		mylog(log_fatal,"error: -c /-s  hasnt been set\n");
+	if (no_l || no_r||program_mode==0)
+	{
+		print_help();
+		myexit(-1);
+	}
+	//if(lower_level)
+		//process_lower_level_arg();
+
+	 mylog(log_info,"important variables: ");
+
+	 log_bare(log_info,"log_level=%d:%s ",log_level,log_text[log_level]);
+	 log_bare(log_info,"raw_mode=%s ",raw_mode_tostring[raw_mode]);
+	 log_bare(log_info,"cipher_mode=%s ",cipher_mode_tostring[cipher_mode]);
+	 log_bare(log_info,"auth_mode=%s ",auth_mode_tostring[auth_mode]);
+
+	 log_bare(log_info,"key=%s ",key_string);
+
+	 log_bare(log_info,"local_ip=%s ",local_ip);
+	 log_bare(log_info,"local_port=%d ",local_port);
+	 log_bare(log_info,"remote_ip=%s ",remote_ip);
+	 log_bare(log_info,"remote_port=%d ",remote_port);
+	 log_bare(log_info,"source_ip=%s ",source_ip);
+	 log_bare(log_info,"source_port=%d ",source_port);
+
+	 log_bare(log_info,"socket_buf_size=%d ",socket_buf_size);
+
+	 log_bare(log_info,"\n");
+}
+
+void pre_process_arg(int argc, char *argv[])//mainly for load conf file
+{
+	int i,j,k;
+	for (i = 0; i < argc; i++)
+	{
+		if(strcmp(argv[i],"--unit-test")==0)
+		{
+			unit_test();
+			myexit(0);
+		}
+
+	}
+
+	for (i = 0; i < argc; i++)
+	{
+		if(strcmp(argv[i],"-h")==0||strcmp(argv[i],"--help")==0)
+		{
+			print_help();
+			myexit(0);
+		}
+
+	}
+
+	if (argc == 1)
+	{
+		print_help();
+		myexit(-1);
+	}
+
+	process_log_level(argc,argv);
+
+	int new_argc=0;
+	vector<string> new_argv;
+
+	int count=0;
+	int pos=-1;
+
+	for (i = 0; i < argc; i++)
+	{
+		if(strcmp(argv[i],"--conf-file")==0)
+		{
+			count++;
+			pos=i;
+			if(i==argc)
+			{
+				mylog(log_fatal,"--conf-file need a parameter\n");
+				myexit(-1);
+			}
+			if(argv[i+1][0]=='-')
+			{
+				mylog(log_fatal,"--conf-file need a parameter\n");
+				myexit(-1);
+			}
+			i++;
+		}
+		else
+		{
+			//printf("<%s>",argv[i]);
+			new_argc++;
+			new_argv.push_back(argv[i]);
+		}
+	}
+	if(count>1)
+	{
+		mylog(log_fatal,"duplicated --conf-file option\n");
+		myexit(-1);
+	}
+
+	if(count>0)
+	{
+		load_config(argv[pos+1],new_argc,new_argv);
+	}
+	char* new_argv_char[new_argv.size()];
+
+	new_argc=0;
+	for(i=0;i<(int)new_argv.size();i++)
+	{
+		if(strcmp(new_argv[i].c_str(),"--conf-file")==0)
+		{
+			mylog(log_fatal,"cant have --conf-file in a config file\n");
+			myexit(-1);
+		}
+		new_argv_char[new_argc++]=(char *)new_argv[i].c_str();
+	}
+	process_arg(new_argc,new_argv_char);
+
+}
+void *run_keep(void *none)  //called in a new thread for --keep-rule option
+{
+
+	while(1)
+	{
+		sleep(iptables_rule_keep_interval);
+		keep_iptables_rule();
+		if(about_to_exit)   //just incase it runs forever if there is some bug,not necessary
+		{
+			sleep(10);
+			keep_thread_running=0; //not thread safe ,but wont cause problem
+			break;
+		}
+	}
+	return NULL;
+
+}
+void iptables_rule()  // handles -a -g --gen-add  --keep-rule
+{
+	if(auto_add_iptables_rule&&generate_iptables_rule)
+	{
+		mylog(log_warn," -g overrides -a\n");
+		auto_add_iptables_rule=0;
+		//myexit(-1);
+	}
+	if(generate_iptables_rule_add&&generate_iptables_rule)
+	{
+		mylog(log_warn," --gen-add overrides -g\n");
+		generate_iptables_rule=0;
+		//myexit(-1);
+	}
+
+	if(keep_rule&&auto_add_iptables_rule==0)
+	{
+		auto_add_iptables_rule=1;
+		mylog(log_warn," --keep_rule implys -a\n");
+		generate_iptables_rule=0;
+		//myexit(-1);
+	}
+	char tmp_pattern[200];
+	string pattern="";
+
+	if(program_mode==client_mode)
+	{
+		if(raw_mode==mode_faketcp)
+		{
+			sprintf(tmp_pattern,"-s %s/32 -p tcp -m tcp --sport %d",remote_ip,remote_port);
+		}
+		if(raw_mode==mode_udp)
+		{
+			sprintf(tmp_pattern,"-s %s/32 -p udp -m udp --sport %d",remote_ip,remote_port);
+		}
+		if(raw_mode==mode_icmp)
+		{
+			sprintf(tmp_pattern,"-s %s/32 -p icmp",remote_ip);
+		}
+		pattern=tmp_pattern;
+	}
+	if(program_mode==server_mode)
+	{
+
+		if(raw_mode==mode_faketcp)
+		{
+			sprintf(tmp_pattern,"-p tcp -m tcp --dport %d",local_port);
+		}
+		if(raw_mode==mode_udp)
+		{
+			sprintf(tmp_pattern,"-p udp -m udp --dport %d",local_port);
+		}
+		if(raw_mode==mode_icmp)
+		{
+			if(local_ip_uint32==0)
+			{
+				sprintf(tmp_pattern,"-p icmp");
+			}
+			else
+			{
+				sprintf(tmp_pattern,"-d %s/32 -p icmp",local_ip);
+			}
+		}
+		pattern=tmp_pattern;
+	}
+/*
+	if(!simple_rule)
+	{
+		pattern += " -m comment --comment udp2rawDwrW_";
+
+		char const_id_str[100];
+		sprintf(const_id_str, "%x_", const_id);
+
+		pattern += const_id_str;
+
+		time_t timer;
+		char buffer[26];
+		struct tm* tm_info;
+
+		time(&timer);
+		tm_info = localtime(&timer);
+
+		strftime(buffer, 26, "%Y-%m-%d-%H:%M:%S", tm_info);
+
+		pattern += buffer;
+
+
+	}*/
+
+	if(auto_add_iptables_rule)
+	{
+		iptables_rule_init(pattern.c_str(),const_id,keep_rule);
+		if(keep_rule)
+		{
+			if(pthread_create(&keep_thread, NULL, run_keep, 0)) {
+
+				mylog(log_fatal, "Error creating thread\n");
+				myexit(-1);
+			}
+			keep_thread_running=1;
+		}
+	}
+	if(generate_iptables_rule)
+	{
+		string rule="iptables -I INPUT ";
+		rule+=pattern;
+		rule+=" -j DROP";
+
+		printf("generated iptables rule:\n");
+		printf("%s\n",rule.c_str());
+		myexit(0);
+	}
+	if(generate_iptables_rule_add)
+	{
+		iptables_gen_add(pattern.c_str(),const_id);
+		myexit(0);
+	}
+
+
+}
+
+int unit_test()
+{
+	printf("running unit test\n");
+	vector<string> conf_lines= {"---aaa","--aaa bbb","-a bbb"," \t \t \t-a\t \t \t bbbbb\t \t \t "};
+	for(int i=0;i<int(conf_lines.size());i++)
+	{
+		printf("orign:%s\n",conf_lines[i].c_str());
+		auto res=parse_conf_line(conf_lines[i]);
+		printf("pasrse_result: size %d",int(res.size()));
+		for(int j=0;j<int(res.size());j++)
+		{
+			printf("<%s>",res[j].c_str());
+		}
+		printf("\n");
+	}
+
+	char s1[]={1,2,3,4,5};
+
+	char s2[]={1};
+
+	short c1=csum((unsigned short*)s1,5);
+	short c2=csum((unsigned short*)s2,1);
+	//c2=0;
+
+	printf("%x %x\n",(int)c1,(int)c2);
+
+	const char buf[]={1,2,3,4,5,6,7,8,9,10,11,2,13,14,15,16};
+	char key[100]={0};
+	char buf2[100]={0};
+	char buf3[100]={0};
+	char buf4[100]={0};
+	int len=16;
+	for(int i=0;i<len;i++)
+	{
+		printf("<%d>",buf[i]);
+	}
+	printf("\n");
+	cipher_encrypt(buf,buf2,len,key);
+	for(int i=0;i<len;i++)
+	{
+		printf("<%d>",buf2[i]);
+	}
+	printf("\n");
+	int temp_len=len;
+	cipher_decrypt(buf2,buf3,len,key);
+	for(int i=0;i<len;i++)
+	{
+		printf("<%d>",buf3[i]);
+	}
+	printf("\n");
+	cipher_encrypt(buf2,buf4,temp_len,key);
+	for(int i=0;i<temp_len;i++)
+	{
+		printf("<%d>",buf4[i]);
+	}
+	return 0;
+}
+
+
+int set_timer(int epollfd,int &timer_fd)//put a timer_fd into epoll,general function,used both in client and server
+{
+	int ret;
+	epoll_event ev;
+
+	itimerspec its;
+	memset(&its,0,sizeof(its));
+
+	if((timer_fd=timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0)
+	{
+		mylog(log_fatal,"timer_fd create error\n");
+		myexit(1);
+	}
+	its.it_interval.tv_sec=(timer_interval/1000);
+	its.it_interval.tv_nsec=(timer_interval%1000)*1000ll*1000ll;
+	its.it_value.tv_nsec=1; //imidiately
+	timerfd_settime(timer_fd,0,&its,0);
+
+
+	ev.events = EPOLLIN;
+	ev.data.u64 = timer_fd;
+
+	ret=epoll_ctl(epollfd, EPOLL_CTL_ADD, timer_fd, &ev);
+	if (ret < 0) {
+		mylog(log_fatal,"epoll_ctl return %d\n", ret);
+		myexit(-1);
+	}
+	return 0;
+}
+
+
+int set_timer_server(int epollfd,int &timer_fd)//only for server
+{
+	int ret;
+	epoll_event ev;
+
+	itimerspec its;
+	memset(&its,0,sizeof(its));
+
+	if((timer_fd=timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0)
+	{
+		mylog(log_fatal,"timer_fd create error\n");
+		myexit(1);
+	}
+	its.it_interval.tv_sec=(timer_interval/1000);
+	its.it_interval.tv_nsec=(timer_interval%1000)*1000ll*1000ll;
+	its.it_value.tv_nsec=1; //imidiately
+	timerfd_settime(timer_fd,0,&its,0);
+
+
+	ev.events = EPOLLIN;
+	ev.data.u64 = pack_u64(2,timer_fd);////difference
+
+	ret=epoll_ctl(epollfd, EPOLL_CTL_ADD, timer_fd, &ev);
+	if (ret < 0) {
+		mylog(log_fatal,"epoll_ctl return %d\n", ret);
+		myexit(-1);
+	}
+	return 0;
+}
+
+int handle_lower_level(raw_info_t &raw_info)//fill lower_level info,when --lower-level is enabled,only for server
+{
+	packet_info_t &send_info=raw_info.send_info;
+	packet_info_t &recv_info=raw_info.recv_info;
+
+	if(lower_level_manual)
+	{
+		memset(&send_info.addr_ll,0,sizeof(send_info.addr_ll));
+		send_info.addr_ll.sll_family=AF_PACKET;
+		send_info.addr_ll.sll_ifindex=ifindex;
+		send_info.addr_ll.sll_halen=ETHER_ADDR_LEN;
+		send_info.addr_ll.sll_protocol=htons(ETH_P_IP);
+		memcpy(&send_info.addr_ll.sll_addr,dest_hw_addr,ETHER_ADDR_LEN);
+		 mylog(log_debug,"[manual]lower level info %x %x\n ",send_info.addr_ll.sll_halen,send_info.addr_ll.sll_protocol);
+	}
+	else
+	{
+	memset(&send_info.addr_ll,0,sizeof(send_info.addr_ll));
+	send_info.addr_ll.sll_family=recv_info.addr_ll.sll_family;
+	send_info.addr_ll.sll_ifindex=recv_info.addr_ll.sll_ifindex;
+	send_info.addr_ll.sll_protocol=recv_info.addr_ll.sll_protocol;
+	send_info.addr_ll.sll_halen=recv_info.addr_ll.sll_halen;
+	memcpy(send_info.addr_ll.sll_addr,recv_info.addr_ll.sll_addr,sizeof(send_info.addr_ll.sll_addr));
+	//other bytes should be kept zero.
+
+	  mylog(log_debug,"[auto]lower level info %x %x\n ",send_info.addr_ll.sll_halen,send_info.addr_ll.sll_protocol);
+	}
+	return 0;
+}
+
+
+

+ 55 - 0
misc.h

@@ -0,0 +1,55 @@
+/*
+ * misc.h
+ *
+ *  Created on: Sep 23, 2017
+ *      Author: root
+ */
+
+#ifndef MISC_H_
+#define MISC_H_
+
+
+#include "common.h"
+#include "log.h"
+#include "network.h"
+
+extern char local_ip[100], remote_ip[100],source_ip[100];//local_ip is for -l option,remote_ip for -r option,source for --source-ip
+extern u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.
+extern int local_port , remote_port,source_port;//similiar to local_ip  remote_ip,buf for port.source_port=0 indicates --source-port is not enabled
+
+extern int force_source_ip; //if --source-ip is enabled
+
+
+extern id_t const_id;//an id used for connection recovery,its generated randomly,it never change since its generated
+
+
+
+extern int udp_fd;  //for client only. client use this fd to listen and handle udp connection
+extern int bind_fd; //bind only,never send or recv.  its just a dummy fd for bind,so that other program wont occupy the same port
+extern int epollfd; //fd for epoll
+extern int timer_fd;   //the general timer fd for client and server.for server this is not the only timer find,every connection has a timer fd.
+extern int fail_time_counter;//determine if the max_fail_time is reached
+extern int epoll_trigger_counter;//for debug only
+extern int debug_flag;//for debug only
+
+
+extern int simple_rule;  //deprecated.
+extern int keep_rule; //whether to monitor the iptables rule periodly,re-add if losted
+extern int auto_add_iptables_rule;//if -a is set
+extern int generate_iptables_rule;//if -g is set
+extern int generate_iptables_rule_add;// if --gen-add is set
+
+extern int debug_resend; // debug only
+
+extern char key_string[1000];// -k option
+
+int process_lower_level_arg();
+void print_help();
+void iptables_rule();
+void pre_process_arg(int argc, char *argv[]);//mainly for load conf file;
+int unit_test();
+int set_timer(int epollfd,int &timer_fd);
+int set_timer_server(int epollfd,int &timer_fd);
+int handle_lower_level(raw_info_t &raw_info);
+
+#endif /* MISC_H_ */