利用libpcap抓取数据包

  • 概述
    • libpcap是一个网络数据包捕获函数库,tcpdump就是以libpcap为基础的。
    • 主要作用:
      • 捕获各种数据包,例如:网络流量统计
      • 过滤网络数据包,例如:过滤掉本地上的一些数据,类似防火墙
      • 分析网络数据包,例如:分析网络协议,数据的采集
      • 存储网络数据包,例如:保存捕获的数据以为将来进行分析
  • libpcap的抓包框架
    • pcap_lookupdev():函数用来查找网络设备,返回可被pcap_open_live()函数调用的网络设备名指针。
    • pcap_lookupnet():函数获得指定网络设备的网络号和掩码。
    • pcap_open_live():函数用于打开设备,并且返回用于捕获网络数据包的数据包捕获描述字。对于此网络设备的操作都要基于此网络设备描述字。
    • pcap_compile():函数用于将用户制定的过滤策略编译到过滤程序中
    • pcap_setfilter():函数用于设置过滤器
    • pcap_loop():与pcap_next()和pcap_next_ex()两个函数一样用来捕获数据包
    • pcap_close():函数用于关闭网络设备,释放资源

上实例:

#include <iostream>
#include <stdio.h>  
#include <pcap.h>  
#ifdef WIN32
#pragma   comment   (lib,"Ws2_32.lib")
#include<Winsock2.h>
#else
#include <arpa/inet.h> 
#endif
#include <time.h>  
#include <stdlib.h>  
#define BUFSIZE 1514  

long total = 0;
struct ether_header
{
	unsigned char ether_dhost[6];   //目的mac  
	unsigned char ether_shost[6];   //源mac  
	unsigned short ether_type;      //以太网类型  
};

/*******************************回调函数************************************/
void callback(unsigned char *argument, const struct pcap_pkthdr *packet_heaher, const unsigned char *packet_content)
{
	unsigned char *mac_string;              //  
	struct ether_header *ethernet_protocol;
	unsigned short ethernet_type;           //以太网类型  
	printf("----------------------------------------------------\n");
	//printf("%s\n", ctime((time_t *)&(packet_heaher->ts.tv_sec))); //转换时间  
	ethernet_protocol = (struct ether_header *)packet_content;

	mac_string = (unsigned char *)ethernet_protocol->ether_shost;//获取源mac地址  
	printf("Mac Source Address is %02x:%02x:%02x:%02x:%02x:%02x\n", *(mac_string + 0), *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
	mac_string = (unsigned char *)ethernet_protocol->ether_dhost;//获取目的mac  
	printf("Mac Destination Address is %02x:%02x:%02x:%02x:%02x:%02x\n", *(mac_string + 0), *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));

	ethernet_type = ntohs(ethernet_protocol->ether_type);//获得以太网的类型  
	printf("Ethernet type is :%04x\n", ethernet_type);
	switch (ethernet_type)
	{
	case 0x0800:printf("The network layer is IP protocol\n"); break;//ip  
	case 0x0806:printf("The network layer is ARP protocol\n"); break;//arp  
	case 0x0835:printf("The network layer is RARP protocol\n"); break;//rarp  
	default:break;
	}
	std::cout << "packnumber :" << total++ << std::endl;;
}

int main(int argc, char *argv[])
{
	char error_content[100];    //出错信息  
	pcap_t * pcap_handle;
	//unsigned char *mac_string;
	//unsigned short ethernet_type;           //以太网类型  
	char *net_interface = NULL;                 //接口名字  
	//struct pcap_pkthdr protocol_header;
	//struct ether_header *ethernet_protocol;

	//获取网络接口  
	net_interface = pcap_lookupdev(error_content);
	if (NULL == net_interface)
	{
		perror("pcap_lookupdev");
		exit(-1);
	}

	pcap_handle = pcap_open_live(net_interface, BUFSIZE, 1, 0, error_content);//打开网络接口  

	struct bpf_program filter;
	pcap_compile(pcap_handle, &filter, "dst port 80", 1, 0);
	pcap_setfilter(pcap_handle, &filter);

	if (pcap_loop(pcap_handle, -1, callback, NULL) < 0)
	{
		perror("pcap_loop");
	}

	pcap_close(pcap_handle);
	return 0;
}

效果还不错

猜你喜欢

转载自blog.csdn.net/liyu123__/article/details/81112056