diff --git a/common.h b/common.h index f5b6960..36978b3 100644 --- a/common.h +++ b/common.h @@ -56,6 +56,7 @@ #include #include #include +#include using namespace std; diff --git a/main.cpp b/main.cpp index abb3d04..54b3b02 100755 --- a/main.cpp +++ b/main.cpp @@ -997,9 +997,11 @@ int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * d int server_on_raw_recv_multi() //called when server received an raw packet { char dummy_buf[buf_len]; - packet_info_t peek_info; + raw_info_t peek_raw_info; + peek_raw_info.peek=1; + packet_info_t &peek_info=peek_raw_info.recv_info; if(pre_recv_raw_packet()<0) return -1; - if(peek_raw(peek_info)<0) + if(peek_raw(peek_raw_info)<0) { discard_raw_packet(); //recv(raw_recv_fd, 0,0, 0 );// @@ -1554,10 +1556,23 @@ int server_event_loop() int i, j, k;int ret; - if(local_addr.inner.ipv4.sin_addr.s_addr!=0) + if(raw_ip_version==AF_INET) { - bind_addr_used=1; - bind_addr=local_addr; + if(local_addr.inner.ipv4.sin_addr.s_addr!=0) + { + bind_addr_used=1; + bind_addr.v4=local_addr.inner.ipv4.sin_addr.s_addr; + } + } + else + { + assert(raw_ip_version==AF_INET6); + char zero_arr[16]={0}; + if(memcmp(&local_addr.inner.ipv6.sin6_addr,zero_arr,16)!=0) + { + bind_addr_used=1; + bind_addr.v6=local_addr.inner.ipv6.sin6_addr; + } } //bind_address_uint32=local_ip_uint32;//only server has bind adress,client sets it to zero diff --git a/misc.cpp b/misc.cpp index 8e313cc..167fa1d 100644 --- a/misc.cpp +++ b/misc.cpp @@ -32,7 +32,9 @@ fd_manager_t fd_manager; //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 -address_t local_addr,remote_addr,source_addr,bind_addr; +address_t local_addr,remote_addr,source_addr; + +my_ip_t bind_addr; int source_port=-1; diff --git a/misc.h b/misc.h index 48a159a..b472b67 100644 --- a/misc.h +++ b/misc.h @@ -78,7 +78,9 @@ union current_state_t //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 address_t local_addr,remote_addr,source_addr,bind_addr; +extern address_t local_addr,remote_addr,source_addr; + +extern my_ip_t bind_addr; extern int bind_addr_used; extern int force_source_ip; //if --source-ip is enabled diff --git a/network.cpp b/network.cpp index ca86389..97ff6e1 100644 --- a/network.cpp +++ b/network.cpp @@ -190,7 +190,7 @@ int init_raw_socket() g_ip_id_counter=get_true_random_number()%65535; if(lower_level==0) { - raw_send_fd = socket(AF_INET , SOCK_RAW , IPPROTO_RAW);// IPPROTO_TCP?? + raw_send_fd = socket(raw_ip_version , SOCK_RAW , IPPROTO_RAW);// IPPROTO_TCP?? if(raw_send_fd == -1) { mylog(log_fatal,"Failed to create raw_send_fd\n"); @@ -606,11 +606,25 @@ int send_raw_packet(raw_info_t &raw_info,const char * packet,int len) int ret; if(lower_level==0) { - struct sockaddr_in sin={0}; - sin.sin_family = AF_INET; - //sin.sin_port = htons(info.dst_port); //dont need this - sin.sin_addr.s_addr = send_info.new_dst_ip.v4; - ret = sendto(raw_send_fd, packet, len , 0, (struct sockaddr *) &sin, sizeof (sin)); + if(raw_ip_version==AF_INET) + { + struct sockaddr_in sin={0}; + sin.sin_family = raw_ip_version; + //sin.sin_port = htons(info.dst_port); //dont need this + sin.sin_addr.s_addr = send_info.new_dst_ip.v4; + ret = sendto(raw_send_fd, packet, len , 0, (struct sockaddr *) &sin, sizeof (sin)); + } + else if(raw_ip_version==AF_INET6) + { + struct sockaddr_in6 sin={0}; + sin.sin6_family = raw_ip_version; + //sin.sin_port = htons(info.dst_port); //dont need this + sin.sin6_addr = send_info.new_dst_ip.v6; + ret = sendto(raw_send_fd, packet, len , 0, (struct sockaddr *) &sin, sizeof (sin)); + }else + { + assert(0==1); + } } else @@ -686,72 +700,7 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen) return send_raw_packet(raw_info,send_raw_ip_buf,ip_tot_len); } -int peek_raw(packet_info_t &peek_info) -{ - //static char peek_raw_buf[buf_len]; - assert(g_packet_buf_cnt==1); - //g_packet_buf_cnt--; - char * peek_raw_buf=g_packet_buf; - int recv_len=g_packet_buf_len; - char *ip_begin=peek_raw_buf+link_level_header_len; - //struct sockaddr saddr={0}; - //socklen_t saddr_size=sizeof(saddr); - //int recv_len = recvfrom(raw_recv_fd, peek_raw_buf,max_data_len, MSG_PEEK ,&saddr , &saddr_size);//change max_data_len to something smaller,we only need header here - iphdr * iph = (struct iphdr *) (ip_begin); - //mylog(log_info,"recv_len %d\n",recv_len); - if(recv_lensaddr; - unsigned short iphdrlen =iph->ihl*4; - char *payload=ip_begin+iphdrlen; - - //mylog(log_info,"protocol %d\n",iph->protocol); - switch(raw_mode) - { - case mode_faketcp: - { - if(iph->protocol!=IPPROTO_TCP) - { - mylog(log_trace,"failed here"); - return -1; - } - struct tcphdr *tcph=(tcphdr *)payload; - if(recv_lensource); - peek_info.syn=tcph->syn; - break; - } - case mode_udp: - { - if(iph->protocol!=IPPROTO_UDP) return -1; - struct udphdr *udph=(udphdr *)payload; - if(recv_lensource); - break; - } - case mode_icmp: - { - if(iph->protocol!=IPPROTO_ICMP) return -1; - struct icmphdr *icmph=(icmphdr *)payload; - if(recv_lenid); - break; - } - default:return -1; - } - return 0; -} int pre_recv_raw_packet() { assert(g_packet_buf_cnt==0); @@ -782,21 +731,29 @@ int discard_raw_packet() g_packet_buf_cnt--; return 0; } -int recv_raw_packet(char * &packet,int &len) +int recv_raw_packet(char * &packet,int &len,int peek) { assert(g_packet_buf_cnt==1); - g_packet_buf_cnt--; + if(!peek) + g_packet_buf_cnt--; if(g_packet_buf_lensaddr; - recv_info.new_dst_ip.v4=iph->daddr; - recv_info.protocol=iph->protocol; + if(raw_packet_len<1) + { + mylog(log_trace,"raw_packet_len <1, dropped\n"); + return -1; + } + iph = (struct iphdr *) (ip_begin); //just use the iphdr here to get the first 4bit + ip6h= (struct ip6_hdr *) (ip_begin); + if(raw_ip_version==AF_INET) + { + if(iph->version!=4) + { + mylog(log_trace,"expect ipv4 packet, but got something else: %02x\n",iph->version); + return -1; + } + if(raw_packet_len<(int)sizeof(iphdr)) + { + mylog(log_trace,"raw_packet_lenversion!=6) + { + mylog(log_trace,"expect ipv6 packet, but got something else: %02x\n",iph->version); + return -1; + } + if(raw_packet_len<(int)sizeof(ip6_hdr)) + { + mylog(log_trace,"raw_packet_lensaddr; + recv_info.new_dst_ip.v4=iph->daddr; + recv_info.protocol=iph->protocol; + iphdrlen =iph->ihl*4; + ip_len=ntohs(iph->tot_len); + } + else + { + //todo flow id + recv_info.new_src_ip.v6=ip6h->ip6_src; + recv_info.new_dst_ip.v6=ip6h->ip6_dst; + iphdrlen=40; + recv_info.protocol=ip6h->ip6_nxt; //todo handle extension headers; + ip_len=ntohs(ip6h->ip6_plen); + } - if (!(iph->ihl > 0 && iph->ihl <=60)) { - mylog(log_trace,"iph ihl error\n"); - return -1; - } - int ip_len=ntohs(iph->tot_len); + //if (!(iph->ihl > 0 && iph->ihl <=60)) { + // mylog(log_trace,"iph ihl error\n"); + // return -1; + // } + if(raw_packet_len ihl*4; + if(raw_ip_version==AF_INET) + { + if(raw_info.peek==0)// avoid cal it twice + { + u32_t ip_chk=csum ((unsigned short *) ip_begin, iphdrlen); - u32_t ip_chk=csum ((unsigned short *) ip_begin, iphdrlen); + if(ip_chk!=0) + { + mylog(log_debug,"ip header error %x\n",ip_chk); + return -1; + } + } + } + else + { - if(ip_chk!=0) - { - mylog(log_debug,"ip header error %x\n",ip_chk); - return -1; - } + } payload=ip_begin+iphdrlen; @@ -877,7 +890,77 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen) return 0; } +int peek_raw(raw_info_t &raw_info) +{ + //static char peek_raw_buf[buf_len]; + //assert(g_packet_buf_cnt==1); + //g_packet_buf_cnt--; + //char * peek_raw_buf=g_packet_buf; + //int recv_len=g_packet_buf_len; + //char *ip_begin=peek_raw_buf+link_level_header_len; + //struct sockaddr saddr={0}; + //socklen_t saddr_size=sizeof(saddr); + //int recv_len = recvfrom(raw_recv_fd, peek_raw_buf,max_data_len, MSG_PEEK ,&saddr , &saddr_size);//change max_data_len to something smaller,we only need header here + //iphdr * iph = (struct iphdr *) (ip_begin); + //mylog(log_info,"recv_len %d\n",recv_len); + //if(recv_lensaddr; + //unsigned short iphdrlen =iph->ihl*4; + //char *payload=ip_begin+iphdrlen; + + packet_info_t &recv_info=raw_info.recv_info; + + char *payload;int payload_len; + if(recv_raw_ip(raw_info,payload,payload_len)!=0) + return -1; + //mylog(log_info,"protocol %d\n",iph->protocol); + switch(raw_mode) + { + case mode_faketcp: + { + if(recv_info.protocol!=IPPROTO_TCP) + { + mylog(log_trace,"failed here"); + return -1; + } + struct tcphdr *tcph=(tcphdr *)payload; + if(payload_lensource); + recv_info.syn=tcph->syn; + break; + } + case mode_udp: + { + if(recv_info.protocol!=IPPROTO_UDP) return -1; + struct udphdr *udph=(udphdr *)payload; + if(payload_lensource); + break; + } + case mode_icmp: + { + if(recv_info.protocol!=IPPROTO_ICMP) return -1; + struct icmphdr *icmph=(icmphdr *)payload; + if(payload_lenid); + break; + } + default:return -1; + } + return 0; +} int send_raw_icmp(raw_info_t &raw_info, const char * payload, int payloadlen) { const packet_info_t &send_info=raw_info.send_info; @@ -1992,7 +2075,7 @@ int recv_raw(raw_info_t &raw_info,char *& payload,int & payloadlen) } }*/ - +/* int get_src_adress(u32_t &ip,u32_t remote_ip_uint32,int remote_port) //a trick to get src adress for a dest adress,so that we can use the src address in raw socket as source ip { struct sockaddr_in remote_addr_in={0}; @@ -2031,7 +2114,7 @@ int get_src_adress(u32_t &ip,u32_t remote_ip_uint32,int remote_port) //a trick close(new_udp_fd); return 0; -} +}*/ int get_src_adress2(address_t &output_addr,address_t remote_addr) { @@ -2052,7 +2135,7 @@ int get_src_adress2(address_t &output_addr,address_t remote_addr) return 0; } - +/* int try_to_list_and_bind(int &fd,u32_t local_ip_uint32,int port) //try to bind to a port,may fail. { int old_bind_fd=fd; @@ -2091,7 +2174,7 @@ int try_to_list_and_bind(int &fd,u32_t local_ip_uint32,int port) //try to bind } } return 0; -} +}*/ int try_to_list_and_bind2(int &fd,address_t address) //try to bind to a port,may fail. { int old_bind_fd=fd; @@ -2131,7 +2214,7 @@ int try_to_list_and_bind2(int &fd,address_t address) //try to bind to a port,ma } return 0; } - +/* int client_bind_to_a_new_port(int &fd,u32_t local_ip_uint32)//find a free port and bind to it. { int raw_send_port=10000+get_true_random_number()%(65535-10000); @@ -2145,7 +2228,7 @@ int client_bind_to_a_new_port(int &fd,u32_t local_ip_uint32)//find a free port a mylog(log_fatal,"bind port fail\n"); myexit(-1); return -1;////for compiler check -} +}*/ int client_bind_to_a_new_port2(int &fd,const address_t& address)//find a free port and bind to it. { diff --git a/network.h b/network.h index 5a45a20..4c281f4 100644 --- a/network.h +++ b/network.h @@ -87,7 +87,8 @@ struct raw_info_t packet_info_t recv_info; //int last_send_len; //int last_recv_len; - + bool peek=0; + //bool csum=1; u32_t reserved_send_seq; //uint32_t first_seq,first_ack_seq; int rst_received=0; @@ -120,7 +121,7 @@ int pre_recv_raw_packet(); int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen); -int peek_raw(packet_info_t &peek_info); +int peek_raw(raw_info_t &peek_info); int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen);