From fed5bdc7007945cfa71322adfd0706ad5e572837 Mon Sep 17 00:00:00 2001 From: wangyu- Date: Thu, 14 Jun 2018 08:01:03 -0500 Subject: [PATCH] libpcap roughly works --- common.h | 45 ++++++++++++++++-- main.cpp | 55 ++++++++++++++++++---- misc.cpp | 2 + misc.h | 2 + network.cpp | 131 +++++++++++++++++++++++++++++++++++++++++++++++++--- network.h | 12 +++++ 6 files changed, 230 insertions(+), 17 deletions(-) diff --git a/common.h b/common.h index 901443d..57b3966 100644 --- a/common.h +++ b/common.h @@ -87,14 +87,53 @@ struct ip_port_t }; - - typedef u64_t fd64_t; const int max_data_len=1800; const int buf_len=max_data_len+400; - const int max_address_len=512; +const int queue_len=2000; + +struct queue_t +{ + char data[queue_len][buf_len]; + int data_len[queue_len]; + + int head=0; + int tail=0; + void clear() + { + head=tail=0; + } + int empty() + { + if(head==tail) return 1; + else return 0; + } + int full() + { + if( (tail+1)%queue_len==head ) return 1; + else return 0; + } + void peek_front(char * & p,int &len) + { + assert(!empty()); + p=data[head]; + len=data_len[head]; + } + void pop_front() + { + assert(!empty()); + head++;head%=queue_len; + } + void push_back(char * p,int len) + { + assert(!full()); + memcpy(data[tail],p,len); + data_len[tail]=len; + tail++;tail%=queue_len; + } +}; u64_t get_current_time(); u64_t pack_u64(u32_t a,u32_t b); diff --git a/main.cpp b/main.cpp index f2b7775..96d5600 100755 --- a/main.cpp +++ b/main.cpp @@ -24,6 +24,9 @@ int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is mylog(log_trace,"\n",send_info.ts_ack); + + //mylog(log_debug,"pcap cnt :%d\n",pcap_cnt); + if(raw_info.disabled) { conn_info.state.client_current_state=client_idle; @@ -278,7 +281,10 @@ int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a p if(conn_info.state.client_current_state==client_idle ) { - recv(raw_recv_fd, 0,0, 0 ); + //recv(raw_recv_fd, 0,0, 0 ); + pthread_mutex_lock(&queue_mutex); + my_queue.pop_front(); + pthread_mutex_unlock(&queue_mutex); } else if(conn_info.state.client_current_state==client_tcp_handshake)//received syn ack { @@ -515,10 +521,36 @@ void udp_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) void raw_recv_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) { + assert(0==1); conn_info_t & conn_info= *((conn_info_t*)watcher->data); client_on_raw_recv(conn_info); } +void async_cb(struct ev_loop *loop, struct ev_async *watcher, int revents) +{ + conn_info_t & conn_info= *((conn_info_t*)watcher->data); + //mylog(log_info,"async_cb called\n"); + while(1) + { + 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) break; + + memcpy(g_packet_buf,p,len); + g_packet_buf_len=len; + assert(g_packet_buf_cnt==0); + g_packet_buf_cnt++; + client_on_raw_recv(conn_info); + } +} void clear_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) { conn_info_t & conn_info= *((conn_info_t*)watcher->data); @@ -677,11 +709,19 @@ int client_event_loop() // myexit(-1); //} - struct ev_io raw_watcher; + //struct ev_io raw_watcher; + + //raw_watcher.data=&conn_info; + // ev_io_init(&raw_watcher, raw_recv_cb, raw_recv_fd, EV_READ); + //ev_io_start(loop, &raw_watcher); + + g_default_loop=loop; + async_watcher.data=&conn_info; + ev_async_init(&async_watcher,async_cb); + ev_async_start(loop,&async_watcher); + + init_raw_socket(); - raw_watcher.data=&conn_info; - ev_io_init(&raw_watcher, raw_recv_cb, raw_recv_fd, EV_READ); - ev_io_start(loop, &raw_watcher); int unbind=1; @@ -825,9 +865,9 @@ int main(int argc, char *argv[]) local_ip_uint32=inet_addr(local_ip); source_ip_uint32=inet_addr(source_ip); - - mylog(log_info,"remote_ip=[%s], make sure this is a vaild IP address\n",remote_ip); + strcpy(remote_ip,remote_address); + mylog(log_info,"remote_ip=[%s], make sure this is a vaild IP address\n",remote_ip); remote_ip_uint32=inet_addr(remote_ip); init_random_number_fd(); @@ -845,7 +885,6 @@ int main(int argc, char *argv[]) md5((uint8_t*)tmp,strlen(tmp),(uint8_t*)key); iptables_rule(); - init_raw_socket(); if(program_mode==client_mode) { diff --git a/misc.cpp b/misc.cpp index d6e1af7..a0b3d23 100644 --- a/misc.cpp +++ b/misc.cpp @@ -82,6 +82,8 @@ int about_to_exit=0; int socket_buf_size=1024*1024; int force_socket_buf=0; + + //char lower_level_arg[1000]; int process_lower_level_arg()//handle --lower-level option { diff --git a/misc.h b/misc.h index 772b52b..2f06944 100644 --- a/misc.h +++ b/misc.h @@ -119,6 +119,8 @@ extern pthread_t keep_thread; extern int keep_thread_running; + + int process_lower_level_arg(); void print_help(); void iptables_rule(); diff --git a/network.cpp b/network.cpp index bea6678..359f4ed 100644 --- a/network.cpp +++ b/network.cpp @@ -41,6 +41,22 @@ const u32_t receive_window_random_range=512; const unsigned char wscale=0x05; libnet_t *libnet_handle; +pcap_t *pcap_handle; +int pcap_link_header_len=-1; +//int pcap_cnt=0; +queue_t my_queue; + +pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER; + +ev_async async_watcher; + +ev_loop* g_default_loop; + +pthread_t pcap_recv_thread; + +char g_packet_buf[buf_len]; //dirty code, fix it later +int g_packet_buf_len=1; +int g_packet_buf_cnt=0; struct sock_filter code_tcp_old[] = { { 0x28, 0, 0, 0x0000000c },//0 @@ -173,14 +189,111 @@ packet_info_t::packet_info_t() } +void *pcap_recv_thread_entry(void *none) +{ + struct pcap_pkthdr *packet_header; + const u_char *pkt_data; + + while(1) + { + //printf("!!!\n"); + int ret=pcap_next_ex(pcap_handle,&packet_header,&pkt_data); + + switch (ret) + { + case 0: + continue; + case 1: + assert(packet_header->caplen <= packet_header->len); + assert(packet_header->caplen <= max_data_len); + if(packet_header->caplenlen) continue; + + if((int)packet_header->caplencaplen)-pcap_link_header_len); + pthread_mutex_unlock(&queue_mutex); + + //pcap_cnt++; + + ev_async_send (g_default_loop,&async_watcher); + break; + + case -1: + mylog(log_fatal,"pcap_next_ex error [%s]\n",pcap_geterr(pcap_handle)); + myexit(-1); + break; + case -2: + assert(0==1); + break; + default: + assert(0==1); + } + } + myexit(-1); +} + +extern void async_cb(struct ev_loop *loop, struct ev_async *watcher, int revents); int init_raw_socket() { - char errbuf[LIBNET_ERRBUF_SIZE]; + char libnet_errbuf[LIBNET_ERRBUF_SIZE]; - libnet_handle = libnet_init(LIBNET_RAW4, dev, errbuf); + libnet_handle = libnet_init(LIBNET_RAW4, dev, libnet_errbuf); + + if(libnet_handle==0) + { + mylog(log_fatal,"libnet_init failed bc of [%s]\n",libnet_errbuf); + myexit(-1); + } + + char pcap_errbuf[PCAP_ERRBUF_SIZE]; + + pcap_handle=pcap_open_live(dev,max_data_len,0,1000,pcap_errbuf); + + if(pcap_handle==0) + { + mylog(log_fatal,"pcap_open_live failed bc of [%s]\n",pcap_errbuf); + myexit(-1); + } + + int ret=pcap_datalink(pcap_handle); + + if(ret==DLT_EN10MB) + { + pcap_link_header_len=14; + } + else if(ret==DLT_NULL) + { + pcap_link_header_len=4; + } + else + { + mylog(log_fatal,"unknown pcap link type : %d\n",ret); + myexit(-1); + } + + + + + + if(pthread_create(&pcap_recv_thread, NULL, pcap_recv_thread_entry, 0)) { + mylog(log_fatal, "Error creating thread\n"); + myexit(-1); + } + /* + if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) { + fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle)); + return(2); + } + if (pcap_setfilter(handle, &fp) == -1) { + fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle)); + return(2); + } + + */ - assert(libnet_handle!=0); g_ip_id_counter=get_true_random_number()%65535; if(lower_level==0) @@ -728,13 +841,20 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen) const packet_info_t &send_info=raw_info.send_info; packet_info_t &recv_info=raw_info.recv_info; - static char recv_raw_ip_buf[buf_len]; + //static char recv_raw_ip_buf[buf_len]; iphdr * iph; struct sockaddr_ll saddr={0}; socklen_t saddr_size = sizeof(saddr); int flag=0; - int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, max_data_len+1, flag ,(sockaddr*)&saddr , &saddr_size); + + //int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, max_data_len+1, flag ,(sockaddr*)&saddr , &saddr_size); + + assert(g_packet_buf_cnt==1); + g_packet_buf_cnt--; + + int recv_len=g_packet_buf_len; + char *recv_raw_ip_buf=g_packet_buf; if(recv_len==max_data_len+1) { @@ -758,7 +878,6 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen) return -1; } - char *ip_begin=recv_raw_ip_buf+link_level_header_len; //14 is eth net header iph = (struct iphdr *) (ip_begin); diff --git a/network.h b/network.h index cfc5e20..ca39844 100644 --- a/network.h +++ b/network.h @@ -27,6 +27,18 @@ extern int random_drop; extern int ifindex; +extern queue_t my_queue; + +extern ev_async async_watcher; +extern ev_loop* g_default_loop; + +extern pthread_mutex_t queue_mutex; +extern int pcap_cnt; + +extern char g_packet_buf[buf_len]; +extern int g_packet_buf_len; +extern int g_packet_buf_cnt; + struct icmphdr { uint8_t type;