Libpcap程式設計(6)
阿新 • • 發佈:2019-01-07
上篇文章中針對libpcap進行了理論總結,以及部分函式和結構的介紹,這裡就整個資料包抓包由淺到深進行分析。
獲取網路介面名字和掩碼資訊
執行結果:#include #include #include//in_addr標頭檔案 int main(int argc,char **argv) { char error[PCAP_ERRBUF_SIZE];//#define PCAP_ERRBUF_SIZE 256 struct in_addr ip; struct in_addr mask; char *interface; bpf_u_int32 net_ip; bpf_u_int32 net_mask; interface=pcap_lookupdev(error);//獲取網路裝置指標 if(interface==NULL) { printf("pcap_lookupdev error\n"); return -1; } printf("Network interface:%s\n",interface); int ret=pcap_lookupnet(interface,&net_ip,&net_mask,error);//獲取網路介面地址和掩碼 if(ret<0) { printf("pcap_lookupnet error\n"); return -1; } ip.s_addr=net_ip; mask.s_addr=net_mask; printf("Interface ip:%s\n",inet_ntoa(ip));//地址輸出 printf("Interface mask:%s\n",inet_ntoa(mask));//掩碼輸出 //獲取所有介面 // typedef struct pcap_if pcap_if_t; /* struct pcap_if { struct pcap_if *next; char *name; char *description; struct pcap_addr *addresses; bpf_u_int32 flags; }; */ pcap_if_t *p; ret=pcap_findalldevs(&p,error); if(ret<0) { printf("pcap_findalldevs error\n"); return -1; } while(p!=NULL) { printf("name:%s",p->name); printf("\tdescription:%s\n",p->description); p=p->next; } return 0; }
注:程式碼中使用了pcap_findalldevs函式獲取主機內所有可用的網路介面連結串列。可以看出顯示中列出了4個USB介面。這是由於USB為傳輸協議,並不是儲存協議,USB介面主要用於資料傳輸的,所以可以抓取到USB介面。
在獲取了網路介面之後開始抓取一個數據包
執行結果:#include #include #include #include int main() { char error[PCAP_ERRBUF_SIZE]; struct pcap_pkthdr head; pcap_t *pcaph;//libpcap控制代碼 struct bpf_program bpf_filter;//過濾規則 char bpf_filter_string[]="src host 192.168.61.118"; const u_char *packet_content;//資料包內容 bpf_u_int32 mask; bpf_u_int32 ip; char *interface; int ret; interface=pcap_lookupdev(error);//返回可用裝置指標 assert(interface!=NULL); printf("interface:%s",interface); ret=pcap_lookupnet(interface,&ip,&mask,error);//獲取網路地址和掩碼資訊 assert(ret>=0); pcaph=pcap_open_live(interface,1500,1,0,error);//開啟網路介面 printf("%s\n",error); assert(pcaph!=NULL); pcap_compile(pcaph,&bpf_filter,bpf_filter_string,0,mask);//編譯過濾規則 pcap_setfilter(pcaph,&bpf_filter); packet_content=pcap_next(pcaph,&head); printf("capture a packet from:%s\n",interface); printf("The packet length is :%d\n",head.len); pcap_close(pcaph); return 0; }
注意:這裡可以列印error字串輸出出錯的原因,該程式中後期核心轉儲是因為適用許可權的問題,適用本程式碼需要有root執行許可權。該段程式碼可以作為資料包捕獲的雛形,後期整個資料包捕獲都是這樣的架構。 抓取多個數據包
執行ping命令:#include #include #include /*注意回撥函式的定義 typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes); */ void packet_callback(u_char *argument,const struct pcap_pkthdr *pcap_header,const u_char *packet_content) { static int num=1; printf("The %d packet is captured\n",num); num++; } int main() { pcap_t *pcaph; char error[PCAP_ERRBUF_SIZE]; char *interface; struct bpf_program bpf_filter; char bpf_filter_string[]="src host 192.168.61.118"; bpf_u_int32 mask; bpf_u_int32 ip; interface=pcap_lookupdev(error); pcap_lookupnet(interface,&ip,&mask,error); pcaph=pcap_open_live(interface,BUFSIZ,1,0,error); pcap_compile(pcaph,&bpf_filter,bpf_filter_string,0,mask); pcap_setfilter(pcaph,&bpf_filter); pcap_loop(pcaph,5,packet_callback,NULL);//迴圈接收5個數據包 pcap_close(pcaph); return 0; }
執行程式碼:
與上一個內容類似,該段程式碼需要要root許可權下執行,否則將會報錯核心轉儲。另外規則的制定需要參考上一篇博文的理論基礎部分。後期的分析將會深入到TCP/IP各個層去,這裡面涉及各層的協議。抓取和分析,這裡作為一個專題講述。(先執行程式碼在主機(192.168.61.117),再使用主機(192.168.61.118)ping(192.168.61.117))