added --fix-gro

This commit is contained in:
wangyu 2019-07-15 08:36:06 -04:00
parent 7d481d26b9
commit ee787e0d4a
11 changed files with 234 additions and 93 deletions

@ -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;
}

@ -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();

@ -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
{

@ -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_ */

@ -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);

@ -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

@ -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

@ -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);

@ -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);

@ -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

@ -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)