WinPcap编程入门(1)——获取本地适配器信息

来源:互联网 发布:php零基础到项目实战 编辑:程序博客网 时间:2024/05/19 13:10

本文转载自:http://www.cnblogs.com/blacksword/  

    第一次听说Winpcap是在做计算机网络实验的时候,那时候要用Ethereal捕获数据包来做分析,而Ethereal需要用到Winpcap包,那时候对Winpcap的概念很粗浅,认为它就是用来捕获数据包的。现在由于项目的原因要用到Winpcap编程,简单来说就是调用Winpcap里面的库函数来捕获网络封包之类的操作。因为没有相关的书籍讲解Winpcap编程,所以就直接参考的Winpcap技术文档,官网上有下载,有英文版的也有中文版的,中文版的是支持到4.01版本。我下载的Winpcap库是4.1.2的,但是由于看到有中文版的就省点事直接看中文版的了,当然同时也会参照英文版的文档,可能有些翻译并不是那么地到位。技术文档里面有Winpcap教程,它从最简单的部分(获得设备列表)到最复杂的部分(控制发送队列并收集和统计网络信息)来展示如何使用Winpcap进行程序开发。由于我是初学者,所以就一步一步、按部就班地按照这个教程来学习。

    第一个实例程序是一个获取设备列表的小程序(所有的示例程序都是用C语言来编写的),下面是源代码(我是在Windows下开发,使用的codeblocks IDE,相对于源码有一些修改)

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <stdio.h>#include <stdlib.h>#define HAVE_REMOTE#include <pcap.h>int main(){    pcap_if_t *alldevs;    pcap_if_t *d;    int i = 0;    char errbuf[PCAP_ERRBUF_SIZE];    /* get local devices */    if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)    {        fprintf(stderr, "Error in pcap_findalldevs_ex: %s\n", errbuf);        exit(1);    }    /* print devices list */    for(d = alldevs; d != NULL; d = d->next)    {        printf("%d. %s", ++i, d->name);        if (d->description)            printf("(%s)\n", d->description);        else            printf("(No description available)\n");    }    if(i == 0)    {        printf("\nNo interfaces found! Make sure Winpcap is installed.\n");        return -1;    }    pcap_freealldevs(alldevs);    return 0;}</span>

    细心的读者可以发现,多了一条宏定义语句"#define HAVE_REMOTE",这句话到底是做什么用的呢?仍然是参考技术文档,有一章“使用Winpcap编程”,在讲到创建一个使用wpcap.dll的应用程序的时候有这么一句话:

      如果你的程序使用了WinPcap的远程捕获功能,那么在预处理定义中加入HAVE_REMOTE不要直接把remote-ext.h直接加入到你的源文件中去。  

    就是说它的作用相当于是包含了remote-ext.h这个头文件,至于为何不直接把这个头文件包含起来,这就不是这一章需要设计的话题了。

    继续查看源码我们发现有两个结构体指针pcap_if_t*的声明,转到pcap_if_t的声明处我们看到在"pcap.h"中有一句

typedef struct pcap_if pcap_if_t;

    pcap_if这个结构体是用来做什么的呢?查看文档我们不难发现,它包含了一个适配器的详细信息,其中的数据域name和description表示一个适配器名称和一个可以让人们理解的描述。而之所以定义结构体指针,因为其实定义的是pcap_if结构的链表。链表我们是再熟悉不过了!接下去分析,PCAP_ERRBUF_SIZE是宏定义的,值为256。然后我们看到了pcap_findalldevs_ex这么一个函数,函数的功能就是返回一个pcap_if结构的链表。函数的完整声明如下所示:

<span style="font-family:KaiTi_GB2312;font-size:18px;">int pcap_findalldevs_ex  ( char *  source,    struct pcap_rmtauth *  auth,    pcap_if_t **  alldevs,    char *  errbuf    ) </span>

    第一个参数是一个字符指针,保存的是source的地址,事实上它决定了source的类型(file, remote/local interface),而PCAP_SRC_IF_STRING表示用户希望从一个网络接口卡打开捕获(open a capture from a network interface)。

    第二个参数是一个pcap_rmtauth的结构体指针,它保存了RPCAP连接远程用户的验证信息,因为是要获取本地的设备列表,这个参数就没有意义,置为NULL。

    第三个参数刚才已经说了,这个函数的功能就是返回一个pcap_if结构的链表,给的是链表的地址,所以在源码中看到写的是“&alldevs”。

    第四个参数是错误信息缓冲,就是说如果这个函数调用出错则把错误信息保存到这个buff里面。

      pcap_findalldevs_ex函数的返回值为0,说明everything is fine,返回-1则表示出错。

    接下来的代码就没什么好说的了。但注意最后有一个pcap_freealldevs的函数,它的功能显而易见,就是释放链表的空间咯!

    最后看一下在本机运行后的结果。显示的是本机连接的设备信息,当然我们看到设备的名称都是以rpcap://打头的,其实就是源码中用到的PCAP_SRC_IF_STRING,这应该是RPCAP协议所定义的格式,这里就不深究了。


0 0
原创粉丝点击