Heatwave's Blog

My site


本文主要参考了以下资料:RaiChen的博客,WinPcap官方文档,《网络分析技术揭秘》-吕雪峰,Phinecos(洞庭散人)的博客

创建项目与配置好后,就可以开始使用WinPcap进行开发了! #1.获取设备列表

接下来,先看一段代码:

#include "pcap.h"

int main()
{
    pcap_if_t *alldevs;
    pcap_if_t *d;
    int i = 0;
    char errbuf[PCAP_ERRBUF_SIZE];

    //获取本地机器设备列表
    if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL /*auth is not needed*/,&alldevs,errbuf) == -1)
    {
        fprintf(stderr,"Error in pcap_findalldevs_ex:%s\n",errbuf);
        exit(1);
    }

    //打印列表
    for(d=alldevs;d!=NULL;d=d->next)
    {
        printf("%d.name:%s\n",++i,d->name);
        if(d->description)
            printf("description:(%s)\n",d->description);
        else
            printf("(No description available)\n");
    }

    if(i == 0)
    {
        printf("\nNo interfaces found!Make sure WinPcap is installed.\n");
        return 0;
    }

    //不再需要设备列表,释放它
    pcap_freealldevs(alldevs);

    system("pause");
    return 0;
}

首先,包含pcap.h头文件,这是必须的。然后定义了两个pcap_if_t的指针,用来指向每一个网络适配器(也就是网卡),pcap_if_t其实是一个pcap_if的结构体,定义如下:

struct pcap_if {
    struct pcap_if *next;
    char *name;     /* name to hand to "pcap_open_live()" */
    char *description;  /* textual description of interface, or NULL */
    struct pcap_addr *addresses;
    bpf_u_int32 flags;  /* PCAP_IF_ interface flags */
};

其中next用来指向下一个适配器,用来构成一个链表,每一个节点都是一个pcap_if的结构,表示一个适配器。name是适配器的名称,可以用来传递给pcap_open_live()函数。description是适配器的详细描述,这个成员变量可能为空。addresses是一个pcap_addr类型的结构体,定义了适配器的一些网络地址,在下面会详细介绍。flags是PCAP_IF_接口标志,目前唯一可能的标志为PCAP_IF_LOOPBACK,也就是在适配器为环回适配器时才设置为该值。

接下来一个char数组errbuf用来写入错误信息,长度为固定的PCAP_ERRBUF_SIZE。

接着就调用pcap_findalldevs_ex()函数获取本机适配器列表:

    if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL /*auth is not needed*/,&alldevs,errbuf) == -1)
    {
        fprintf(stderr,"Error in pcap_findalldevs_ex:%s\n",errbuf);
        exit(1);
    }

pcap_findalldevs_ex()函数原型如下:

int pcap_findalldevs_ex(
    char *  source,
    struct pcap_rmtauth *   auth,
    pcap_if_t **    alldevs,
    char *  errbuf
)

函数第一个参数source表示从哪一个源读取适配器信息,我这里设置的是常量PCAP_SRC_IF_STRING,也就是rpcap://,表示读取本机适配器信息。如果是rpcap://host:port则表示读取远程主机的适配器信息,是file://c:/myfolder/则表示读取某个目录下的pcap文件

第二个参数auth是连接远程主机时请求授权的,我们是在本地嗅探的就用不着了,设置为NULL就行。

第三个参数alldevs类型就是我们上面介绍的pcap_if结构体,把我们上面定义的alldevs的地址传进去,如果函数返回0,一切正常的话,alldevs将会指向适配器列表的第一个元素,列表的每一个元素都是pcap_if结构,每一个元素表示一个适配器。

第四个参数errbuf用来存储错误信息。

函数的返回值为0表示一切正常,返回值为-1表示有错误发生,如果返回值为-1我们就输出errbuf里的错误信息,并以exit(1)退出程序。

接下来用一个相同结构的指针d指向alldevs,循环打印每一个适配器的name和description:

    for(d=alldevs;d!=NULL;d=d->next)
    {
        printf("%d.name:%s\n",++i,d->name);
        if(d->description)
            printf("description:(%s)\n",d->description);
        else
            printf("(No description available)\n");
    }

注意description有可能为空,要判断一下。然后d=d->next指向下一个适配器,直到d为空。

在循环的时候每读到一个适配器上面定义的i都会加1,如果i为0的话,表示读不到任何一个适配器,于是输出错误信息然后返回0:

    if(i == 0)
    {
        printf("\nNo interfaces found!Make sure WinPcap is installed.\n");
        return 0;
    }

最后调用pcap_freealldevs()函数释放pcap_findalldevs_ex()函数获得的适配器信息,也就是alldevs指向的内容:

    pcap_freealldevs(alldevs);

这样就结束了!

运行一下程序,得到如下结果:Sniffer_ObtainingTheDeviceList

获取了适配器的基本信息后,我们继续获取一些适配器的高级信息。下一篇:获取适配器高级信息