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