Browse Source

added --fix-gro

wangyu 6 years ago
parent
commit
ee787e0d4a
11 changed files with 234 additions and 93 deletions
  1. 81 64
      client.cpp
  2. 6 2
      common.h
  3. 84 11
      connection.cpp
  4. 4 3
      connection.h
  5. 7 1
      encrypt.cpp
  6. 1 2
      encrypt.h
  7. 5 0
      makefile
  8. 5 0
      misc.cpp
  9. 20 1
      network.cpp
  10. 0 1
      network.h
  11. 21 8
      server.cpp

+ 81 - 64
client.cpp

@@ -307,6 +307,77 @@ int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is
 	}
 	return 0;
 }
+int client_on_raw_recv_hs2_or_ready(conn_info_t &conn_info,char type,char *data,int data_len)
+{
+    packet_info_t &send_info=conn_info.raw_info.send_info;
+    packet_info_t &recv_info=conn_info.raw_info.recv_info;
+
+    if(!recv_info.new_src_ip.equal(send_info.new_dst_ip)||recv_info.src_port!=send_info.dst_port)
+    {
+        mylog(log_warn,"unexpected adress %s %s %d %d,this shouldnt happen.\n",recv_info.new_src_ip.get_str1(),send_info.new_dst_ip.get_str2(),recv_info.src_port,send_info.dst_port);
+        return -1;
+    }
+
+    if(conn_info.state.client_current_state==client_handshake2)
+    {
+        mylog(log_info,"changed state from to client_handshake2 to client_ready\n");
+        conn_info.state.client_current_state=client_ready;
+        conn_info.last_hb_sent_time=0;
+        conn_info.last_hb_recv_time=get_current_time();
+        conn_info.last_oppsite_roller_time=conn_info.last_hb_recv_time;
+        client_on_timer(conn_info);
+    }
+    if(data_len>=0&&type=='h')
+    {
+        mylog(log_debug,"[hb]heart beat received,oppsite_roller=%d\n",int(conn_info.oppsite_roller));
+        conn_info.last_hb_recv_time=get_current_time();
+        return 0;
+    }
+    else if(data_len>= int( sizeof(u32_t))&&type=='d')
+    {
+        mylog(log_trace,"received a data from fake tcp,len:%d\n",data_len);
+
+        if(hb_mode==0)
+            conn_info.last_hb_recv_time=get_current_time();
+
+        u32_t tmp_conv_id;
+        memcpy(&tmp_conv_id,&data[0],sizeof(tmp_conv_id));
+        tmp_conv_id=ntohl(tmp_conv_id);
+
+        if(!conn_info.blob->conv_manager.c.is_conv_used(tmp_conv_id))
+        {
+            mylog(log_info,"unknow conv %d,ignore\n",tmp_conv_id);
+            return 0;
+        }
+
+        conn_info.blob->conv_manager.c.update_active_time(tmp_conv_id);
+
+        //u64_t u64=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
+        address_t tmp_addr=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
+
+        //sockaddr_in tmp_sockaddr={0};
+
+        //tmp_sockaddr.sin_family = AF_INET;
+        //tmp_sockaddr.sin_addr.s_addr=(u64>>32u);
+
+        //tmp_sockaddr.sin_port= htons(uint16_t((u64<<32u)>>32u));
+
+
+        int ret=sendto(udp_fd,data+sizeof(u32_t),data_len -(sizeof(u32_t)),0,(struct sockaddr *)&tmp_addr.inner,tmp_addr.get_len());
+
+        if(ret<0)
+        {
+            mylog(log_warn,"sento returned %d,%s,%02x,%s\n",ret,get_sock_error(),int(tmp_addr.get_type()),tmp_addr.get_str());
+            //perror("ret<0");
+        }
+    }
+    else
+    {
+        mylog(log_warn,"unknown packet,this shouldnt happen.\n");
+        return -1;
+    }
+    return 0;
+}
 int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a packet.
 {
 	char* data;int data_len;
@@ -427,75 +498,21 @@ int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a p
 	}
 	else if(conn_info.state.client_current_state==client_handshake2||conn_info.state.client_current_state==client_ready)//received heartbeat or data
 	{
-		char type;
-		if(recv_safer(conn_info,type,data,data_len)!=0)
+		vector<char> type_vec;
+		vector<string> data_vec;
+		if(recv_safer_multi(conn_info,type_vec,data_vec)!=0)
 		{
 			mylog(log_debug,"recv_safer failed!\n");
 			return -1;
 		}
-		if(!recv_info.new_src_ip.equal(send_info.new_dst_ip)||recv_info.src_port!=send_info.dst_port)
-		{
-			mylog(log_warn,"unexpected adress %s %s %d %d,this shouldnt happen.\n",recv_info.new_src_ip.get_str1(),send_info.new_dst_ip.get_str2(),recv_info.src_port,send_info.dst_port);
-			return -1;
-		}
-		if(conn_info.state.client_current_state==client_handshake2)
-		{
-			mylog(log_info,"changed state from to client_handshake2 to client_ready\n");
-			conn_info.state.client_current_state=client_ready;
-			conn_info.last_hb_sent_time=0;
-			conn_info.last_hb_recv_time=get_current_time();
-			conn_info.last_oppsite_roller_time=conn_info.last_hb_recv_time;
-			client_on_timer(conn_info);
-		}
-		if(data_len>=0&&type=='h')
-		{
-			mylog(log_debug,"[hb]heart beat received,oppsite_roller=%d\n",int(conn_info.oppsite_roller));
-			conn_info.last_hb_recv_time=get_current_time();
-			return 0;
-		}
-		else if(data_len>= int( sizeof(u32_t))&&type=='d')
-		{
-			mylog(log_trace,"received a data from fake tcp,len:%d\n",data_len);
-
-			if(hb_mode==0)
-				conn_info.last_hb_recv_time=get_current_time();
-
-			u32_t tmp_conv_id;
-			memcpy(&tmp_conv_id,&data[0],sizeof(tmp_conv_id));
-			tmp_conv_id=ntohl(tmp_conv_id);
 
-			if(!conn_info.blob->conv_manager.c.is_conv_used(tmp_conv_id))
-			{
-				mylog(log_info,"unknow conv %d,ignore\n",tmp_conv_id);
-				return 0;
-			}
-
-			conn_info.blob->conv_manager.c.update_active_time(tmp_conv_id);
-
-			//u64_t u64=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
-			address_t tmp_addr=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
-
-			//sockaddr_in tmp_sockaddr={0};
-
-			//tmp_sockaddr.sin_family = AF_INET;
-			//tmp_sockaddr.sin_addr.s_addr=(u64>>32u);
-
-			//tmp_sockaddr.sin_port= htons(uint16_t((u64<<32u)>>32u));
-
-
-			int ret=sendto(udp_fd,data+sizeof(u32_t),data_len -(sizeof(u32_t)),0,(struct sockaddr *)&tmp_addr.inner,tmp_addr.get_len());
-
-			if(ret<0)
-			{
-		    	mylog(log_warn,"sento returned %d,%s,%02x,%s\n",ret,get_sock_error(),int(tmp_addr.get_type()),tmp_addr.get_str());
-				//perror("ret<0");
-			}
-		}
-		else
-		{
-			mylog(log_warn,"unknown packet,this shouldnt happen.\n");
-						return -1;
-		}
+		for(int i=0;i<(int)type_vec.size();i++)
+        {
+		    char type=type_vec[i];
+		    char *data=(char *)data_vec[i].c_str(); //be careful, do not append data to it
+		    int data_len=data_vec[i].length();
+            client_on_raw_recv_hs2_or_ready(conn_info, type, data,data_len);
+        }
 
 		return 0;
 	}

+ 6 - 2
common.h

@@ -159,6 +159,8 @@ const int max_addr_len=100;
 
 extern int force_socket_buf;
 
+extern int g_fix_gro;
+
 /*
 struct ip_port_t
 {
@@ -345,10 +347,12 @@ struct not_copy_able_t
 	}
 };
 
-
-const int max_data_len=1800;
+const int single_max_data_len=1800;
+const int max_data_len=single_max_data_len*10;
 const int buf_len=max_data_len+400;
 
+//const int max_data_len_gro=max_data_len*10;
+//const int buf_len_gro=max_data_len_gro+400;
 //const int max_address_len=512;
 
 u64_t get_current_time();

+ 84 - 11
connection.cpp

@@ -11,8 +11,6 @@
 
 int disable_anti_replay=0;//if anti_replay windows is diabled
 
-
-
 const int disable_conn_clear=0;//a raw connection is called conn.
 
 conn_manager_t conn_manager;
@@ -462,12 +460,9 @@ int send_safer(conn_info_t &conn_info,char type,const char* data,int len)  //saf
 	}
 
 
-
 	char send_data_buf[buf_len];  //buf for send data and send hb
 	char send_data_buf2[buf_len];
 
-
-
 	my_id_t n_tmp_id=htonl(conn_info.my_id);
 
 	memcpy(send_data_buf,&n_tmp_id,sizeof(n_tmp_id));
@@ -488,10 +483,25 @@ int send_safer(conn_info_t &conn_info,char type,const char* data,int len)  //saf
 
 	int new_len=len+sizeof(n_seq)+sizeof(n_tmp_id)*2+2;
 
-	if(my_encrypt(send_data_buf,send_data_buf2,new_len)!=0)
-	{
-		return -1;
-	}
+	if(g_fix_gro==0)
+    {
+        if (my_encrypt(send_data_buf, send_data_buf2, new_len) != 0)
+        {
+            return -1;
+        }
+    }
+	else
+    {
+        if (my_encrypt(send_data_buf, send_data_buf2+2, new_len) != 0)
+        {
+            return -1;
+        }
+        write_u16(send_data_buf2,new_len);
+        send_data_buf2[0]^=gro_xor[0];
+        send_data_buf2[1]^=gro_xor[1];
+        new_len+=2;
+    }
+
 
 	if(send_raw0(conn_info.raw_info,send_data_buf2,new_len)!=0) return -1;
 
@@ -602,19 +612,82 @@ int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len
 
 	return 0;
 }
-int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len)///safer transfer function with anti-replay,when mutually verification is done.
+int recv_safer_notused(conn_info_t &conn_info,char &type,char* &data,int &len)///safer transfer function with anti-replay,when mutually verification is done.
 {
 	packet_info_t &send_info=conn_info.raw_info.send_info;
 	packet_info_t &recv_info=conn_info.raw_info.recv_info;
 
 	char * recv_data;int recv_len;
-	static char recv_data_buf[buf_len];
+	//static char recv_data_buf[buf_len];
 
 	if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1;
 
 	return reserved_parse_safer(conn_info,recv_data,recv_len,type,data,len);
 }
 
+int recv_safer_multi(conn_info_t &conn_info,vector<char> &type_arr,vector<string> &data_arr)///safer transfer function with anti-replay,when mutually verification is done.
+{
+    packet_info_t &send_info=conn_info.raw_info.send_info;
+    packet_info_t &recv_info=conn_info.raw_info.recv_info;
+
+    char * recv_data;int recv_len;
+    assert(type_arr.empty());
+    assert(data_arr.empty());
+
+    if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1;
+
+    char type;
+    char *data;
+    int len;
+
+    if(g_fix_gro==0)
+    {
+        int ret = reserved_parse_safer(conn_info, recv_data, recv_len, type, data, len);
+        if(ret==0)
+        {
+            type_arr.push_back(type);
+            data_arr.emplace_back(data,data+len);
+            //std::copy(data,data+len,data_arr[0]);
+        }
+        return ret;
+    } else
+    {
+        while(recv_len>2)
+        {
+            recv_len-=2;
+            int single_len;
+            recv_data[0]^=gro_xor[0];
+            recv_data[1]^=gro_xor[1];
+            single_len=read_u16(recv_data);
+            recv_data+=2;
+            if(single_len > recv_len)
+            {
+                mylog(log_debug,"illegal single_len %d, recv_len %d left,dropped\n",single_len,recv_len);
+                break;
+            }
+            if(single_len> single_max_data_len )
+            {
+                mylog(log_warn,"single_len %d > %d\n",single_len,single_max_data_len);
+            }
+
+            int ret = reserved_parse_safer(conn_info, recv_data, single_len, type, data, len);
+
+            if(ret!=0)
+            {
+                mylog(log_debug,"illegal single_len %d, recv_len %d left,dropped\n",single_len,recv_len);
+            } else{
+                type_arr.push_back(type);
+                data_arr.emplace_back(data,data+len);
+                //std::copy(data,data+len,data_arr[data_arr.size()-1]);
+            }
+            recv_data+=single_len;
+            
+        }
+        return 0;
+    }
+}
+
+
 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
 {

+ 4 - 3
connection.h

@@ -18,8 +18,6 @@ extern int disable_anti_replay;
 
 const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short.
 
-
-
 struct anti_replay_t  //its for anti replay attack,similar to openvpn/ipsec 's anti replay window
 {
 	u64_t max_packet_received;
@@ -346,5 +344,8 @@ int send_handshake(raw_info_t &raw_info,my_id_t id1,my_id_t id2,my_id_t id3);//
 int send_safer(conn_info_t &conn_info,char type,const char* data,int len);  //safer transfer function with anti-replay,when mutually verification is done.
 int send_data_safer(conn_info_t &conn_info,const char* data,int len,u32_t conv_num);//a wrap for  send_safer for transfer data.
 //int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len);//subfunction for recv_safer,allow overlap
-int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done.
+
+//int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done.
+
+int recv_safer_multi(conn_info_t &conn_info,vector<char> &type_arr,vector<string> &data_arr);//new api for handle gro
 #endif /* CONNECTION_H_ */

+ 7 - 1
encrypt.cpp

@@ -26,6 +26,8 @@ unsigned char hmac_key_decrypt[hmac_key_len + 100];  //key for hmac
 unsigned char cipher_key_encrypt[cipher_key_len + 100];  //key for aes etc.
 unsigned char cipher_key_decrypt[cipher_key_len + 100];  //key for aes etc.
 
+char gro_xor[16+100];//dirty fix for gro
+
 unordered_map<int, const char *> auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"},{auth_hmac_sha1,"hmac_sha1"},};
 
 unordered_map<int, const char *> cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cfb,"aes128cfb"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"},};
@@ -48,9 +50,10 @@ int my_init_keys(const char * user_passwd,int is_client)
 
 	md5((uint8_t*)tmp,strlen(tmp),(uint8_t*)normal_key);
 
+
 	if(auth_mode==auth_hmac_sha1)
 		is_hmac_used=1;
-	if(is_hmac_used)
+	if(is_hmac_used||g_fix_gro)
 	{
 		unsigned char salt[400]="";
 		char salt_text[400]="udp2raw_salt1";
@@ -82,6 +85,9 @@ int my_init_keys(const char * user_passwd,int is_client)
 		assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_cipher_decrypt,strlen(info_cipher_decrypt), cipher_key_decrypt, cipher_key_len )  ==0);
 		assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_encrypt,strlen(info_hmac_encrypt), hmac_key_encrypt, hmac_key_len )  ==0);
 		assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_decrypt,strlen(info_hmac_decrypt), hmac_key_decrypt, hmac_key_len )  ==0);
+
+        const char *gro_info="gro";
+        assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)gro_info,strlen(gro_info), (unsigned char *)gro_xor, 16 )  ==0);
 	}
 	
 	print_binary_chars(normal_key,16);

+ 1 - 2
encrypt.h

@@ -34,8 +34,7 @@ extern cipher_mode_t cipher_mode;
 extern unordered_map<int, const char *> auth_mode_tostring;
 extern unordered_map<int, const char *> cipher_mode_tostring;
 
-
-
+extern char gro_xor[16+100];
 
 int cipher_decrypt(const char *data,char *output,int &len,char * key);//internal interface ,exposed for test only
 int cipher_encrypt(const char *data,char *output,int &len,char * key);//internal interface ,exposed for test only

+ 5 - 0
makefile

@@ -8,6 +8,8 @@ cc_mips24kc_le=/toolchains/lede-sdk-17.01.2-ramips-mt7621_gcc-5.4.0_musl-1.1.16.
 cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
 #cc_arm=/toolchains/lede-sdk-17.01.2-brcm2708-bcm2708_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/staging_dir/toolchain-arm_arm1176jzf-s+vfp_gcc-5.4.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-muslgnueabi-g++
 #cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ 
+cc_tmp= /home/wangyu/OpenWrt-SDK-15.05-x86-64_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-x86_64_gcc-4.8-linaro_uClibc-0.9.33.2/bin/x86_64-openwrt-linux-uclibc-g++
+
 FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers ${OPT}
 
 COMMON=main.cpp lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp  connection.cpp misc.cpp fd_manager.cpp client.cpp server.cpp -lpthread my_ev.cpp -isystem libev
@@ -35,6 +37,9 @@ debug2: git_version
 dynamic: git_version
 	${cc_local}   -o ${NAME}_$@          -I. ${SOURCES} ${FLAGS} -lrt -O3
 
+tmp:git_version
+	${cc_tmp}   -o ${NAME}_$@    -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
+
 mips24kc_be: git_version
 	${cc_mips24kc_be}  -o ${NAME}_$@   -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
 mips24kc_be_asm_aes: git_version

+ 5 - 0
misc.cpp

@@ -298,6 +298,7 @@ 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},
+        {"fix-gro", no_argument,    0, 1},
 		{NULL, 0, 0, 0}
 	  };
 
@@ -738,6 +739,10 @@ void process_arg(int argc, char *argv[])  //process all options
 				use_tcp_dummy_socket=1;
 				mylog(log_info,"--easy-tcp enabled, now a dummy tcp socket will be created for handshake and block rst\n");
 			}
+            else if(strcmp(long_options[option_index].name,"fix-gro")==0)
+            {
+                g_fix_gro=0;
+            }
 			else
 			{
 				mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt);

+ 20 - 1
network.cpp

@@ -9,6 +9,8 @@
 #include "log.h"
 #include "misc.h"
 
+int g_fix_gro=1;
+
 int raw_recv_fd=-1;
 int raw_send_fd=-1;
 u32_t link_level_header_len=0;//set it to 14 if SOCK_RAW is used in socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
@@ -839,10 +841,27 @@ int pre_recv_raw_packet()
 
 	if(g_packet_buf_len==max_data_len+1)
 	{
-		mylog(log_warn,"huge packet, data_len > %d,dropped\n",max_data_len);
+		mylog(log_warn,"huge packet, data_len %d > %d(max_data_len),dropped\n",g_packet_buf_len,max_data_len);
 		return -1;
 	}
 
+    if(g_packet_buf_len> single_max_data_len+1)
+    {
+        if(g_fix_gro==0)
+        {
+            mylog(log_warn, "huge packet, data_len %d > %d(single_max_data_len) dropped\n", g_packet_buf_len,
+                  single_max_data_len);
+            return -1;
+        }
+        else
+        {
+            mylog(log_debug, "huge packet, data_len %d > %d(single_max_data_len) dropped\n", g_packet_buf_len,
+                  single_max_data_len);
+            return -1;
+        }
+
+    }
+
 	if(g_packet_buf_len<0)
 	{
 		mylog(log_trace,"recv_len %d\n",g_packet_buf_len);

+ 0 - 1
network.h

@@ -31,7 +31,6 @@ extern char g_packet_buf[buf_len];
 extern int g_packet_buf_len;
 extern int g_packet_buf_cnt;
 
-
 struct my_iphdr
   {
 #ifdef UDP2RAW_LITTLE_ENDIAN

+ 21 - 8
server.cpp

@@ -411,7 +411,10 @@ int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * d
 	}
 	return 0;
 }
-
+int server_on_recv_safer_multi(conn_info_t &conn_info,char type,char *data,int data_len)
+{
+    return 0;
+}
 int server_on_raw_recv_multi() //called when server received an raw packet
 {
 	char dummy_buf[buf_len];
@@ -590,13 +593,23 @@ int server_on_raw_recv_multi() //called when server received an raw packet
 	}
 	if(conn_info.state.server_current_state==server_ready)
 	{
-		char type;
-		//mylog(log_info,"before recv_safer\n");
-		if (recv_safer(conn_info,type, data, data_len) != 0) {
-			return -1;
-		}
-		//mylog(log_info,"after recv_safer\n");
-		return server_on_raw_recv_ready(conn_info,ip_port,type,data,data_len);
+        vector<char> type_vec;
+        vector<string> data_vec;
+        if(recv_safer_multi(conn_info,type_vec,data_vec)!=0)
+        {
+            mylog(log_debug,"recv_safer failed!\n");
+            return -1;
+        }
+
+        for(int i=0;i<(int)type_vec.size();i++)
+        {
+            char type=type_vec[i];
+            char *data=(char *)data_vec[i].c_str(); //be careful, do not append data to it
+            int data_len=data_vec[i].length();
+            server_on_raw_recv_ready(conn_info,ip_port,type,data,data_len);
+        }
+        return 0;
+
 	}
 
 	if(conn_info.state.server_current_state==server_idle)