1. 程式人生 > >Libpcap程式設計(6)

Libpcap程式設計(6)

上篇文章中針對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執行許可權。該段程式碼可以作為資料包捕獲的雛形,後期整個資料包捕獲都是這樣的架構。 抓取多個數據包
#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;
}

執行ping命令:


執行程式碼:


與上一個內容類似,該段程式碼需要要root許可權下執行,否則將會報錯核心轉儲。另外規則的制定需要參考上一篇博文的理論基礎部分。後期的分析將會深入到TCP/IP各個層去,這裡面涉及各層的協議。抓取和分析,這裡作為一個專題講述。(先執行程式碼在主機(192.168.61.117),再使用主機(192.168.61.118)ping(192.168.61.117))