From 63950e2b227734596ec0121635760b3a6306de89 Mon Sep 17 00:00:00 2001 From: wangyu- Date: Fri, 15 Jun 2018 06:47:39 -0500 Subject: [PATCH] new option pcap-send --- main.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++-- misc.cpp | 8 +++++- network.cpp | 62 ++++++++++++++++++++++++++++++++------------ network.h | 7 +++++ 4 files changed, 132 insertions(+), 19 deletions(-) diff --git a/main.cpp b/main.cpp index 2863ca2..50e8ab6 100755 --- a/main.cpp +++ b/main.cpp @@ -12,6 +12,10 @@ char hb_buf[buf_len]; int on_epoll_recv_event=0; //TODO, just a flag to help detect epoll infinite shoot + +u32_t detect_interval=1500; +u64_t laste_detect_time=0; + int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is ready in epoll { packet_info_t &send_info=conn_info.raw_info.send_info; @@ -26,6 +30,47 @@ int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is //mylog(log_debug,"pcap cnt :%d\n",pcap_cnt); + if(send_with_pcap&&!pcap_header_captured) + { + + if(get_current_time()-laste_detect_time>detect_interval) + { + laste_detect_time=get_current_time(); + } + else + { + return 0; + } + + struct sockaddr_in remote_addr_in={0}; + + socklen_t slen = sizeof(sockaddr_in); + //memset(&remote_addr_in, 0, sizeof(remote_addr_in)); + remote_addr_in.sin_family = AF_INET; + remote_addr_in.sin_port = htons(remote_port); + remote_addr_in.sin_addr.s_addr = remote_ip_uint32; + + int new_udp_fd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(new_udp_fd<0) + { + mylog(log_warn,"create udp_fd error\n"); + return -1; + } + setnonblocking(new_udp_fd); + u64_t tmp=get_true_random_number(); + + int ret=sendto(new_udp_fd,(char*)(&tmp),sizeof(tmp),0,(struct sockaddr *)&remote_addr_in,sizeof(remote_addr_in)); + if(ret==-1) + { + mylog(log_warn,"sendto() failed\n"); + } + + close(new_udp_fd); + + mylog(log_info,"waiting for a use-able packet to be captured\n"); + + return 0; + } if(raw_info.disabled) { @@ -530,6 +575,30 @@ void async_cb(struct ev_loop *loop, struct ev_async *watcher, int revents) { conn_info_t & conn_info= *((conn_info_t*)watcher->data); + if(send_with_pcap&&!pcap_header_captured) + { + int empty=0;char *p;int len; + pthread_mutex_lock(&queue_mutex); + empty=my_queue.empty(); + if(!empty) + { + my_queue.peek_front(p,len); + my_queue.pop_front(); + } + pthread_mutex_unlock(&queue_mutex); + if(empty) return; + + pcap_header_captured=1; + assert(pcap_link_header_len!=-1); + memcpy(pcap_header_buf,p,pcap_link_header_len); + + log_bare(log_info,"link level header captured:\n"); + for(int i=0;i",(u32_t)(unsigned char)pcap_header_buf[i]); + log_bare(log_info,"\n"); + return ; + } + //mylog(log_info,"async_cb called\n"); while(1) { @@ -545,8 +614,9 @@ void async_cb(struct ev_loop *loop, struct ev_async *watcher, int revents) if(empty) break; - memcpy(g_packet_buf,p,len); - g_packet_buf_len=len; + int new_len=len-pcap_link_header_len; + memcpy(g_packet_buf,p+pcap_link_header_len,new_len); + g_packet_buf_len=new_len; assert(g_packet_buf_cnt==0); g_packet_buf_cnt++; client_on_raw_recv(conn_info); diff --git a/misc.cpp b/misc.cpp index 52cc2bc..1b92554 100644 --- a/misc.cpp +++ b/misc.cpp @@ -284,6 +284,7 @@ void process_arg(int argc, char *argv[]) //process all options {"set-ttl", required_argument, 0, 1}, {"dev", required_argument, 0, 1}, {"dns-resolve", no_argument, 0, 1}, + {"pcap-send", no_argument, 0, 1}, {NULL, 0, 0, 0} }; @@ -670,11 +671,16 @@ void process_arg(int argc, char *argv[]) //process all options enable_dns_resolve=1; mylog(log_info,"dns-resolve enabled\n"); } - else if(strcmp(long_options[option_index].name,"dev")==0) // currently not used + else if(strcmp(long_options[option_index].name,"dev")==0) { sscanf(optarg,"%s",dev); mylog(log_info,"dev=[%s]\n",dev); } + else if(strcmp(long_options[option_index].name,"pcap-send")==0) + { + send_with_pcap=1; + mylog(log_info,"--pcap-send enabled, now pcap will be used for sending packet instead of libnet\n"); + } else { mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt); diff --git a/network.cpp b/network.cpp index 5bb0760..b1d8614 100644 --- a/network.cpp +++ b/network.cpp @@ -63,6 +63,10 @@ libnet_ptag_t g_ptag=0; struct bpf_program g_filter; +int send_with_pcap=0; +int pcap_header_captured=0; +int pcap_header_buf[buf_len]; + /* struct sock_filter code_tcp_old[] = { { 0x28, 0, 0, 0x0000000c },//0 @@ -209,7 +213,7 @@ void my_packet_handler( pthread_mutex_lock(&queue_mutex); if(!my_queue.full()) - my_queue.push_back((char *)pkt_data+pcap_link_header_len,(int)(packet_header->caplen)-pcap_link_header_len); + my_queue.push_back((char *)pkt_data,(int)(packet_header->caplen)); pthread_mutex_unlock(&queue_mutex); //pcap_cnt++; @@ -280,6 +284,7 @@ int init_raw_socket() pcap_handle = pcap_create( dev, pcap_errbuf ); + if(pcap_handle==0) { mylog(log_fatal,"pcap_create failed bc of [%s]\n",pcap_errbuf); @@ -291,6 +296,11 @@ int init_raw_socket() assert( pcap_set_timeout(pcap_handle, 1) ==0); assert( pcap_set_immediate_mode(pcap_handle,1) ==0); + if(send_with_pcap) + { + pcap_setdirection(pcap_handle,PCAP_D_INOUT); + } + int ret = pcap_activate( pcap_handle ); if( ret < 0 ) { @@ -315,17 +325,22 @@ int init_raw_socket() myexit(-1); } - //mylog(log_info,"filter expression is [%s]\n",filter_exp); - if (pcap_compile(pcap_handle, &g_filter, "", 0, PCAP_NETMASK_UNKNOWN ) == -1) { + char filter_exp[1000]; + + assert(source_ip_uint32!=0); + + sprintf(filter_exp,"src %s and dst %s and (tcp or udp or icmp)",my_ntoa(source_ip_uint32),remote_ip); + + if (pcap_compile(pcap_handle, &g_filter, filter_exp, 0, PCAP_NETMASK_UNKNOWN ) == -1) { printf("Bad filter - %s\n", pcap_geterr(pcap_handle)); assert(0==1); } - /* + if (pcap_setfilter(pcap_handle, &g_filter) == -1) { printf("Error setting filter - %s\n", pcap_geterr(pcap_handle)); assert(0==1); - }*/ + } if(pthread_create(&pcap_recv_thread, NULL, pcap_recv_thread_entry, 0)) { @@ -459,7 +474,7 @@ void init_filter(int port) mylog(log_info,"filter expression is [%s]\n",filter_exp); - pthread_mutex_lock(&filter_mutex);//not sure if mutex is needed here + //pthread_mutex_lock(&filter_mutex);//not sure if mutex is needed here pcap_freecode(&g_filter); @@ -474,7 +489,7 @@ void init_filter(int port) assert(0==1); } - pthread_mutex_unlock(&filter_mutex); + //pthread_mutex_unlock(&filter_mutex); /* if(disable_bpf_filter) return; //if(raw_mode==mode_icmp) return ; @@ -778,7 +793,8 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen) { const packet_info_t &send_info=raw_info.send_info; const packet_info_t &recv_info=raw_info.recv_info; - char send_raw_ip_buf[buf_len]; + char send_raw_ip_buf0[buf_len+pcap_link_header_len]; + char * send_raw_ip_buf=send_raw_ip_buf0+pcap_link_header_len; if(raw_info.disabled) { @@ -820,21 +836,35 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen) /*if(lower_level) iph->check = csum ((unsigned short *) send_raw_ip_buf, iph->ihl*4); //this is not necessary ,kernel will always auto fill this - else*/ + else iph->check=0; + */ + if(! send_with_pcap) + { + g_ptag=libnet_build_ipv4(ip_tot_len, iph->tos, ntohs(iph->id), ntohs(iph->frag_off), + iph->ttl , iph->protocol , iph->check , iph->saddr, iph->daddr, + (const unsigned char *)payload, payloadlen, libnet_handle, g_ptag); - g_ptag=libnet_build_ipv4(ip_tot_len, iph->tos, ntohs(iph->id), ntohs(iph->frag_off), - iph->ttl , send_info.protocol, iph->check , iph->saddr, iph->daddr, - (const unsigned char *)payload, payloadlen, libnet_handle, g_ptag); + assert(g_ptag!=-1 &&g_ptag!=0); - assert(g_ptag!=-1 &&g_ptag!=0); + int ret; + ret= libnet_write(libnet_handle); - int ret; - ret= libnet_write(libnet_handle); + assert(ret!=-1); + } + else + { + iph->tot_len=htons(ip_tot_len); + iph->check =csum ((unsigned short *) send_raw_ip_buf, iph->ihl*4); - assert(ret!=-1); + + assert(pcap_header_captured==1); + assert(pcap_link_header_len!=-1); + memcpy(send_raw_ip_buf0,pcap_header_buf,pcap_link_header_len); + assert(pcap_sendpacket(pcap_handle,(const unsigned char *)send_raw_ip_buf0,ip_tot_len+pcap_link_header_len)==0); + } diff --git a/network.h b/network.h index c922d6b..0ca75e1 100644 --- a/network.h +++ b/network.h @@ -39,6 +39,12 @@ extern char g_packet_buf[buf_len]; extern int g_packet_buf_len; extern int g_packet_buf_cnt; +extern int pcap_link_header_len; + +extern int send_with_pcap; +extern int pcap_header_captured; +extern int pcap_header_buf[buf_len]; + struct icmphdr { uint8_t type; @@ -210,6 +216,7 @@ struct raw_info_t };//g_raw_info; + int init_raw_socket(); void init_filter(int port);