其他分享
首页 > 其他分享> > WinPcap网络分析原理

WinPcap网络分析原理

作者:互联网

WinPcap是在windows平台访问网络数据链路层的开源库,允许应用程序绕开网络协议栈来捕获与发送网络数据包,并具备内核空间的数据包过滤、网络统计等其他有用特性。同时,WinPcap是众多网络分析工具使用的软件库,在网络分析中具有软件基石的作用。

大多数网络应用程序是通过操作系统来访问网络的,操作系统已经处理了底层的细节问题(协议栈处理)。但有些时候需要直接使用网络中的“原始”数据包,WinPcap提供以下功能:

(1)捕获原始数据包

(2)在数据包传递给应用程序之前,根据指定规则过滤数据包

(3)将原始数据包发送到网络中;

(4)统计网络流量与状态信息。

一、获取与释放网络设备列表

int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf);
int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevsp, char *errbuf);
int pcap_freealldevs(pcap_if_t *alldevsp);

pcap_findalldevs、pcap_findalldevs_ex函数用于返回所找到的适配器列表alldevsp,函数操作成功返回0,否则返回-1。pcap_freealldevs函数用于释放适配器列表。

注意:pcap_findalldevs函数只列出本机的网络设备,pcap_findalldevs_ex函数可以列出远程机器上的网络设备,且能列出一个给定pcap格式的文件。在只列出本机网络设备时,pcap_findalldevs_ex函数中调用pcap_findalldevs函数实现。统一用pcap_findalldevs_ex函数即可。

结构体pcap_if_t是pcap_if的重命名,定义如下

struct pcap_if {
	struct pcap_if *next;                /* 指向下一个结构体 */
	char *name;		                     /* 接口设备名称 */
	char *description;	                 /* 接口设备描述, or NULL */
	struct pcap_addr *addresses;         /* 接口设备地址结构体 */   
	bpf_u_int32 flags;	                 /* 标志 */
};
struct pcap_addr {
	struct pcap_addr *next;
	struct sockaddr *addr;		/* address */
	struct sockaddr *netmask;	/* netmask for that address */
	struct sockaddr *broadaddr;	/* broadcast address for that address */
	struct sockaddr *dstaddr;	/* P2P destination address for that address */
};

 示例:

pcap_if_t *alldevs;
pcap_if_t *d;
char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) != -1)
{
    ...
}

for (d = alldevs; d !=NULL; d = d->next)
{
    ...
}

二、打开与关闭网络设备

pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf);
pcap_t *pcap_open_offline(const char *fname, char *errbuf);
pcap_t *pcap_open_dead(int linktype, int snaplen);
pcap_t *pcap_close(pcap_t *p);

pcap_open函数打开一个通用的数据捕获源(本地主机、远程主机、文件三种类型),以便进行捕获或发送操作;pcap_open_live函数打开本地主机网络设备,并进行数据捕获;pcap_open_offline函数用于打开一个libpcap格式的存储文件,读取数据包;pcap_open_dead函数用于创建一个pcap_t结构体,不捕获数据。

注意:pcap_open函数可代替所有的pcap_open_xxx函数,通过捕获源字符串const char *source来判断源的类型,从而调用具体的打开函数pcap_open_xxx。因此,在开发过程中统一用pcap_open函数即可。pcap_findalldevs_ex返回的网络设备可以直接被pcap_open函数使用,如果用户需要自定义文件来读取,需在source参数中给出。

示例:

pcap_t *adhandle;
adhandle= pcap_open_live(d->name,	    // 设备名称或文件名称
						65536,			// 捕获时保留数据包的长度,存入缓冲区,最大为6536,表示整个包都缓存
					    1,				// 捕获数据包所需的标识
						1000,			// 超时时间,以毫秒为单位,可以理解为抓包的采样间隔
						errbuf			// error buffer
						)

三、数据包的接收 

int	pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
int	pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
u_char* pcap_next(pcap_t *p, struct pcap_pkthdr *h);
int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data);
void pcap_breakloop(pcap_t *p);

 pcap_loop、pcap_dispatch函数用于循环接收一组数据包;pcap_next用于返回下一个可用的数据包;pcap_next_ex用于从网络设备或文件中读取一个数据包;pcap_breakloop用于设置一个标志位,强制pcap_loop或pcap_dispatch函数返回,不再循环。

pcap_loop、pcap_dispatch函数需要调用回调函数pcap_handler callback,由回调函数捕获数据包。定义如下:

void pcap_handler(u_char *user, const struct pcap_pkthdr *header, const u_char *pkt_data);

该函数的参数:user是用户定义的参数,包含了捕获会话的状态,对应于pcap_loop、pcap_dispatch函数的user参数;pcap_pkthdr *header是NPF驱动程序给数据包附加的信息头,不是协议头;u_char *pkt_data指向数据包的数据,包括协议头。

注意:pcap_loop和pcap_dispatch的区别在于,pcap_dispatch函数在超时时间到了就会返回,而pcap_loop不会因此返回,直到cnt个数据包捕获完成后才会返回(或者遇到pcap_breakloop返回)。因此pcap_loop函数会在一小段时间内阻塞网络

pcap_next函数返回u_char类型指针,指向数据包数据(不包含给数据包添加的头信息pcap_pkthdr结构体);pcap_next_ex函数返回操作结果,数据包读取成功返回1,超时返回0,出现错误返回-1,文件操作遇到文件尾部EOF返回-2。与pcap_next_ex相比,pcap_next有两点不足:一是效率低下,尽管隐藏了回调方式,但依赖于pcap_dispatch函数;二是不能检测文件末尾的EOF状态。

示例:

pcap_t *adhandle;
struct pcap_pkthdr *header;
const u_char *pkt_data;
while((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0)
{
    ...
}

 

标签:函数,int,数据包,char,网络分析,原理,WinPcap,pcap,struct
来源: https://blog.csdn.net/zhang1806618/article/details/115322219