WinPcap是一个开源的,运行于Win32平台下的体系结构,它的主要功能时进行数据包捕获和网络分析。它允许应用程序进行协议栈捕获和传输网络数据包,也包括内核级别的数据包过滤、网络静态引擎和支持远程数据包捕获等有用的功能。
WinPcap提供了以下强大的功能:
1.捕获原始的数据包。
2.设置filter,只捕获自己感兴趣的数据包。
3.方便的把捕获的数据包输出到文件和从文件中输入。
4.发送原始的数据包。
5.统计网络流量。
WinPcap的一些基本的功能的实现:
1.捕获数据包
a)枚举所有可用的设备[pcap_findalldevs_ex];
b)通过名字打开一个设备[pcap_open()];
在这里可以打开一个文件,只是再打开这个文件前需要通过pcap_createsrcstr创建相应的name string。
c)设置Filter[pcap_compile,pcap_setfilter];
d)捕获数据。
有几种捕获数据的方法,捕获的数据都是最原始的数据包,即包含数据链路层的数据头。
(1)是以回调的方式[pcap_loop,pcap_dispatch()]
这两会总方法基本相同,底层收集数据包,当满足一定的条件(timeout或者缓冲区满),就会调用回调函数,把收集到的原始数据包S交给用户。他们返回的数据缓冲区包含多个包。
(2)pcap_next_ex()的方式
当一个包到达以后,pcap_next_ex就会返回,返回的数据缓冲区里包含一个包。
2.发送数据包
WinPcap中有发送单个包和发送多个包的方法。
a)通过名字打开设备[pcap_open];
b)自己构造一个原始数据包(这个数据包会不经过任何处理就发送出去,所以必须把保重的各个字段设置好。另外这个数据包是包含数据链路层报头的)。
c)使用pcap_sendpacket()发送数据包。
3.统计网络流量
a)通过名字打开一个设备[pcap_open];
通过read_timeout来设置统计的时间间隔。
b)设置filter[pcap_compile,pcap_setfilter];
c)设置设备为统计模式[pcap_setmode(MODE_STAT)];
d)开始统计,pcap_loop/pcap_dispatch();
e)在回调函数的参数中就报刊了统计信息。
WinPcap由3个模块组成,一个是工作在内核级的NPF包过滤器;另外两个在用户级,即用户级的wpcap.dll模块以及一个动态链接库packet.dll。
NPF的构架的核心,它主要功能是过滤数据包,在包上附加时间戳,数据包长度等信息。第二个模块packet.dll在Win32平台上提供了与NPF的一个通用接口,基于packet.dll的应用程序可以在没有重新编译的情况下运行于不同的Win32平台。Packet.dll还有几个附加功能,他可以用来获得适配器名称,动态驱动加载以及获得主机验码及以太网冲突次数等。第三个模块wpcap.dll是通过调用packet.dll提供的函数生成的,它包括了过滤器生成的一系列可以被用户调用的高级函数,另外还有诸如数据包统计及发送功能。
整个包捕获结构的饿基础是NDIS(网络驱动器接口规范),它是windows中最低端的与联网有关的软件,主要是为各种应用协议与网卡之间提供的一套接口函数,包驱动器的tap函数就是通过调用这些函数实现其数据采集功能的。
Wpcap.dll中的一些函数:
Pcap_setbuff:该函数用来设置包驱动器缓冲区的大小,一个适当大小的缓冲器不仅可以减少丢包率,还可以提高包捕获的速度。
Pcap_setmode:该函数可把网络适配器设置为统计模式。
Pcap_stats:这个函数用于获得包捕获过程的统计数据。
Pcap_open_live:这是最重要的一个函数,首先,他打开网络适配器,把网卡设置为“混杂模式”,使它能够接收来自网络的所有数据包;其次,他为应用程序设置一个缺省大小为256kB的缓冲器;最后,它为包捕获驱动器分配一个缺省为1MB的内核缓冲器,用户以后可以根据需要,改变该缓冲器的大小。
Pcap_read:这个函数从包捕获驱动器中读取一组数据包并针对每个包运行包过滤程序,然后把过滤后的数据送到应用程序缓冲器。
Pcap_setfilter:该函数在包捕获驱动器中设置一个新的包过滤器。过滤器程序则在一个名为bpf_program的结构中定义。
Pcap_loop:该函数可以连续读取并处理指定数目的包,对每个包进行相关处理,处理程序名有所带参数指定,如果指定的数目为0,则处理到包捕获过程的结束或者遇到了某个错误。
注:在项目属性爷>配置属性>链接器>输入>附加依赖项中加入:wpcap.lib;packet.lib;
/* 流量监控程序 */
#include<pcap.h>
#define HAVE_REMOTE
#include<remote-ext.h>
#include<iostream>
using namespace std;
//------------------------------------------------------------------------
void dispatcher_handler(u_char*user_data,const struct pcap_pkthdr* pkthdr,const u_char*pktdata);
//------------------------------------------------------------------------
int main(int argc,char* argv[])
{
int i;
pcap_if_t* alldevs;
pcap_if_t* dev;
char errorbuf[PCAP_ERRBUF_SIZE];
int choice;
pcap_t* stathandle;
WSADATA wsadata;
struct timeval timestamp;
//enum alld evice
if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errorbuf)==-1)
{
cerr<<"pcap_findalldevs_exfailed!("<<errorbuf<<""<<endl;
return(-1);
}
for(i=0,dev=alldevs;dev!=NULL;dev=dev->next)
{
cout<<++i<<'\t'<<dev->name<<endl;
}
if(i==0)
{
cerr<<"no device found!"<<endl;
return(-2);
}
//choose a device
while(1)
{
cout<<"please choice adevice:";
cin>>choice;
if(choice>=1&& choice<=i)
break;
cerr<<"input error,you shall choose a device from list"<<endl;
}
//move to the chosen device
for(i=0,dev=alldevs;i<choice-1;i++,dev=dev->next);
if((stathandle=pcap_open(dev->name,100,PCAP_OPENFLAG_PROMISCUOUS,500, NULL,errorbuf))==NULL)
{
cerr<<"opendevicefailed![device:"<<dev->name<<"]"<<errorbuf<<endl;
pcap_freealldevs(alldevs);
return(-3);
}
cout<<"is Stat "<<dev->name<<"..."<<endl;
pcap_freealldevs(alldevs);
pcap_setmode(stathandle,MODE_STAT);
timestamp.tv_sec=0;
timestamp.tv_usec=0;
pcap_loop(stathandle,0,dispatcher_handler,(unsigned char*)×tamp);
pcap_close(stathandle);
return 0;
}
//------------------------------------------------------------------------
void dispatcher_handler(u_char*user_data,const struct pcap_pkthdr* pkthdr,const u_char* pktdata)
{
static struct timeval tstamp=*((struct timeval*)user_data);
LARGE_INTEGER Bps,Pps;
unsigned long delay;
char strtime[32];
delay=(pkthdr->ts.tv_sec-tstamp.tv_sec)*1000000-tstamp.tv_usec+pkthdr->ts.tv_usec;
Pps.QuadPart=((*(LONGLONG*)(pktdata))*1000000)/delay;
Bps.QuadPart=((*(LONGLONG*)(pktdata+8))*1000000)/delay;
time_t time_=pkthdr->ts.tv_sec;
struct tm* ltime=localtime(&time_);
strftime(strtime,sizeof(strtime),"%H:%M:%S",ltime);
printf("%s:",strtime);
printf("\tPps=%I64u\tBps=%I64u\r\n",Pps.QuadPart,Bps.QuadPart);
tstamp=pkthdr->ts;
}