您的位置:首页 > 其它

深度剖析WinPcap之(八)——打开与关闭适配器(3)

2010-06-22 23:56 288 查看
本文转自http://eslxf.blog.51cto.com/918801/204274



1.4 wpcap.dll中相应函数接口的实现

下面对各函数在wpcap.dll中的实现进行详细分析。

1.4.1 pcap_open函数

函数首先确认参数source的长度不超过PCAP_BUF_SIZE,然后调用pcap_parsesrcstr()函数分析源的种类,是文件,本地主机接口还是远程主机接口,并依据不同的源类型作不同的处理。
如果是文件类型,直接调用pcap_open_offline函数处理。
如果是远程主机接口类型,调用pcap_create()创建一个pcap_t结构体,然后调用函数pcap_opensource_remote()通过打开一个远程主机的适配器,最后给pcap_t结构体几个重要成员设置合适的值,包括捕获数据包长度、读取超时,与pcap_startcapture()需要使用的标识。
如果是本地主机接口类型,直接调用pcap_open_live()函数,然后给NPF驱动设置几个标识。根据需要,可设置禁止回环数据包捕获,还可设置一次读操作所需获得的最小数据长度(字节为单位)。
最后函数返回一个pcap_t结构体指针,供后面的调用使用。
函数主要代码如下:

pcap_t *pcap_open(const char *source,

int snaplen, int flags, int read_timeout,
struct pcap_rmtauth *auth, char *errbuf)
{
char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE];
int type;
pcap_t *fp;
int result;

/*确认source的长度不超过PCAP_BUF_SIZE*/
if (strlen(source) > PCAP_BUF_SIZE)
{//错误,函数返回

}

/*分析源的种类,文件,本地主机接口还是远程主机接口)*/
if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1)
return NULL;

/*依据不同的源类型作不同的处理*/
switch (type)
{
//文件类型,直接调用pcap_open_offline函数处理
case PCAP_SRC_FILE:
fp = pcap_open_offline(name, errbuf);
break;

//远程主机接口类型,打开远程主机的适配器,设置几个重要标识的值。
case PCAP_SRC_IFREMOTE:
//创建pcap_t结构体
fp= pcap_create(source, errbuf);
if (fp == NULL)
{
return NULL;
}

//打开一个远程主机的适配器
result= pcap_opensource_remote(fp, auth);

if (result != 0)
{
pcap_close(fp);
return NULL;
}
//设置捕获数据包长度、读取超时,
//与pcap_startcapture()需要使用的标识。
fp->snapshot= snaplen;
fp->md.timeout= read_timeout;
fp->rmt_flags= flags;
break;

//本地主机接口类型,直接调用pcap_open_live()函数,
//然后给NPF驱动设置几个标识。
case PCAP_SRC_IFLOCAL:

fp = pcap_open_live(name, snaplen, (flags &
PCAP_OPENFLAG_PROMISCUOUS), read_timeout, errbuf);

#ifdef WIN32
//这些标识仅被Windows支持
if (fp != NULL && fp->adapter != NULL)
{
/* 如果需要,禁止回环数据包捕获*/
if(flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
{
if(!PacketSetLoopbackBehavior(fp->adapter,
NPF_DISABLE_LOOPBACK))
{ //设置失败,函数返回

}
}

/*如果需要,设置一次读操作所需获得的最小数据长度(字节为单位)*/
if(flags & PCAP_OPENFLAG_MAX_RESPONSIVENESS)
{
if(!PacketSetMinToCopy(fp->adapter, 0))
{//设置失败,函数返回

}
}
}
#endif //WIN32
break;
default:
//不支持的源类型
strcpy(errbuf, "Source type not supported");
return NULL;
}
return fp;

}

其中函数pcap_parsesrcstr()通过解析一个源字符串,来分析源的种类,是文件,本地主机接口还是远程主机接口)并返回分离出来的内容(type,host,port,name)。函数原型如下:

int pcap_parsesrcstr(const char *source, int *type,

char *host, char *port, char *name, char *errbuf)

参数source为要分析的源名称。。参数host、port与name分别返回源的主机、端口与名称,针对不同的源类型,该三个参数可能为空值。参数errbuf保存函数的错误信息。
其中参数type返回源的类型,WinPcap内部用来表示源的类型的各标识如下:
PCAP_SRC_FILE指明为一个文件,用户希望从一个本地文件获得数据包。
PCAP_SRC_IFLOCAL指明为一个本机接口,比如用户希望从一个本地主机接口获得数据包。不采用RPCAP协议。
PCAP_SRC_IFREMOTE指明为一个远程接口,比如用户希望从一个远程主机接口获得数据包。需要采用RPCAP协议。

其中函数pcap_opensource_remote()通过打开一个RPCAP连接等方式,打开一个远程主机的适配器。函数原型如下:

int pcap_opensource_remote(pcap_t *fp, struct pcap_rmtauth *auth)

参数fp是一个指向pcap_t结构体的指针,该结构体在前面由pcap_create()函数所创建。参数auth是认证权限。
如果函数成功,返回0值,fp指针能够被用来作为后续调用的参数(如pcap_compile()等等)。如果函数失败,返回-1值,fp->errbuf中存储错误信息。
该函数为一个远程接口完成与pcap_open_live()基本类似的功能。不同的是,此处,在调用pcap_startcapture_remote()之前,捕获线程并不启动。因为,在远程捕获时,我们不能在“open adapter”命令一发送出去就开始捕获数据。考虑远程适配器已经负载很重的时候,如果我们开始一个捕获(其默认情况下,具有一个NULL过滤器),新的网络流量将使网络饱和。
作为替代方案,我们想先"open"适配器,接着仅当在我们准备好开始捕获时发送一个"start capture"的命令。该函数作了这样的工作:它发送一个“open adapter”命令(根据RPCAP协议),但是它不开始捕获。
既然其它的libpcap函数并不一定共享该工作方式,我们不得不做一些并不优雅的事情,使得每件事情都能妥善的解决。
注意:万一在捕获还没有开始时,就调用了pcap_compile()函数,过滤器将被存储到pcap_t结构体中,稍后它将被发送到另一个主机(当pcap_startcapture_remote()被调用时)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: