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

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 为要分析的源名称。 。参数hostportname分别返回源的主机、端口与名称,针对不同的源类型,该三个参数可能为空值。参数 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()被调用时)。

你可能感兴趣的:(职场,休闲,winpcap)