霹雳布袋戏老剧:WinPcap基础知识(第一课:获得设备列表)

来源:百度文库 编辑:中财网 时间:2024/05/05 04:09:22
一个基本的WinPcap应用程序所需的第一件事情是获得合适的网络适配器。Libpcap/ Winpcap提供 pcap_findalldevs() 函数完成这个功能:这个函数返回一个相连的pcap_if结构的列表。列表的每一项包含关于适配器的复杂的信息。特别的,name和description域数据包含设备的名称和可读的描述。如下的代码提取设备列表,然后打印到屏幕上。如果没有发现适配器,则显示一个错误。  view plaincopy to clipboardprint?
#include   
 
void 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 /* 这个参数在这里不需要 */, &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. %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;  
    }  
 
    /* We don't need any more the device list. Free it */ 
    pcap_freealldevs(alldevs);  

#include void 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 /* 这个参数在这里不需要 */, &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. %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;
    }    /* We don't need any more the device list. Free it */
    pcap_freealldevs(alldevs);
}  在第一行 #include 的前面加上#define HAVE_REMOTE,或者你在项目属性里面添加“C语言预处理程序定义”一栏里面加上HAVE_REMOTE(注意用‘,’隔开)。加上HAVE_REMOTE,因为在pcap.h头文件里面对此进行判断,如果定义了符号HAVE_REMOTE,pcap.h头文件会自动包含文件,而该文件中申明了函数pcap_findalldevs_ex()以及宏定义PCAP_SRC_IF_STRING。 另外注意一下,在vs2003下面编译的时候,要把项目属性里面的预处理器定义(宏定义)要加上_MBCS的定义,默认的创建VC++控制台应用程序里面是没有该符号的定义的,如果没有该符号定义,编译上面的程序会提示出错。
代码的解释如下(部分):  
首先,象其他libpcap函数一样, pcap_findalldevs()具有一个errbuf参数。该参数指向一个由libpcap填充的字符串。当有错误发生时,错误的描述被写入到这个字符串。
     其次,记住不是libpcap支持的所有的操作系统提供网络适配器的描述,因此如果我们想要编写一个可移植的应用程序,我们必须考虑description为null的情况。在这种情况下我们打印"No description available" 这个字符串。
     最后注意当我们使用列表完成后我们用pcap_freealldevs() 函数释放了它。
     试着编译和运行第一个例子。为了在Unix或者Cygwin下编译它,输入:
gcc -o testaprog testprog.c -lpcap
在Windows下,你需要建立一个project。按照"Using WinPcap in your programs " 的介绍。不过,我建议你使用WinPcap 开发包(在http://winpcap.polito.it 提供下载)。开发包提供很多正确设置的示例程序,并且包含本指南所有代码和编译示例所需的项目、包含文件和库。
编译完成,在我的WinXP工作站上运行程序,结果是
1. {4E273621-5161-46C8-895A-48D0E52A0B83} (Realtek RTL8029(AS) Ethernet Adapter)
2. {5D24AE04-C486-4A96-83FB-8B5EC6C7F430} (3Com EtherLink PCI)
现在你可以看到,Windows下网络适配器的名称(当打开设备时会传递给libpcap)基本上不知所云,也就是说可读性不好,所以旁边的描述对读者将十分有用。   
本课用到的数据结构简介:  
①pcap_if 结构:  
⑴typedef struct pcap_if pcap_if_t      pcap_if在incs/pcap.h文件的72行有定义,在程序里面用此结构,要#include ⑵pcap_if结构里面的数据域:  
  pcap_if *  next :如果非空,是指向下一个元素的指针;如果是NULL,表示是最后一个元素了。   char *  name  :一个指向字符串的指针,该字符串表示一个设备的名字,作为一个参数传递给pcap_open_live()
   char *description;   textual description of interface, or NULL
  pcap_addr * addresses :指向接口的地址列表的第一个元素   u_int flags  : PCAP_IF_INTERFACE 标志。目前唯一可以的标志是PCAP_IF_LOOPBACK,当接口是回送接口(loopback)   ②pcap_addr结构:代表一个接口地址,在中定义  
数据域:  
pcap_addr * 
 next
 
 
 if not NULL, a pointer to the next element in the list; NULL for the last element of the list
 
sockaddr * 
 addr
 
 
 a pointer to a struct sockaddr containing an address
 
sockaddr * 
 netmask
 
 
 if not NULL, a pointer to a struct sockaddr that contains the netmask corresponding to the address pointed to by addr.
 
sockaddr * 
 broadaddr
 
 
 if not NULL, a pointer to a struct sockaddr that contains the broadcast address corre­ sponding to the address pointed to by addr; may be null if the interface doesn't support broadcasts
 
sockaddr * 
 dstaddr
 
 
 if not NULL, a pointer to a struct sockaddr that contains the destination address corre­ sponding to the address pointed to by addr; may be null if the interface isn't a point- to-point interface
 
⑶函数说明  
int pcap_findalldevs_ex  (  char *  source,    struct pcap_rmtauth *  auth,    pcap_if_t **  alldevs,    char *  errbuf  ) pcap_findalldevs_ex函数获得网络设备的一个列表,并且这个列表可以被pcap_open()打开。  
      Pcap_findalldevs_ex()是pcap_findalldevs()的超集,后者是以前的老函数,它只能列出在本地机器的设备。相反,pcap_findalldevs_ex可以列出远程及其上面的设备。除此之外,它还可以列出某个给定的具体目录下面的所有的pcap文件的列表。而且,pcap_findalldevs_ex()还是平台独立的,因为它依靠标准的pcap_findalldevs()来在本地机器上获得地址 。和pcap_findalldevs()不同的是,该函数获得接口名称(alldevs->name )已经可以直接作为参数传递给pcap_open()进行调用。但是pcap_findalldevs_ex()不能,它得到的结果必须要先用  
Pcap_createsrcstr()进行格式化,然后把source 标识符传递给pcap_open()。  
      如果该函数必须列出远程机器上的接口,它打开一个新的控制连接来连接远程机器,然后获得接口,完成后就释放连接。但是,如果该函数检测到远程机器是处于非活动状态,这个连接不会被释放。  
    参数说明:  
Source : 该变量告诉函数在哪儿去查找,它和pcap_open()使用通用的语法。它是一个字符串,用来存放源位置(source location),例如:source 可以是”rpcap://”,表示本地适配器;也可以是”rpcap://host:port”,表示远程主机上面的适配器;还可以是pcap文件,例如:source可以是”rpcap://c:/myfolder/”。  
auth:指向pcap_rmtauth结构的指针,用来保存连接到远程主机上授权信息。在查询本地机器时,此参数没什么意义,可以为NULL。  
alldevs: 指向pcap_if_t结构的指针,该指针不需要初始化,它会在函数的调用过程中进行初始化。此函数返回时,该指针被设置为所获得的设备接口列表的第一个元素,列表的每一个元素都是  
Pcap_if_t结构。  
errbuf :指向用户分配的缓冲区(大小为PCAP_ERRBUF_SIZE),该buf用来存放出错信息。  
返回值:  
成功返回0,alldevs返回设备列表,alldevs不会为NULL。否则返回-1,那就是说系统没有任何接口可以列举的。  
出错的消息在errbuf里面返回,错误可能由下面的原因造成的:  
①    libpcap/winpcap在本地/远程主机上没有安装。  
②    用户没有足够的权限来列举设备/文件  
③    网络问题  
④    其它的错误(比如没有足够的内存或者其它原因)  
注意的问题:  
      接口列表一定要手动释放,通过调用pcap_freealldevs()函数。   Source参数的语法:  
⑴两个宏定义:  
   #define  PCAP_SRC_FILE_STRING  “ file://”    #define  PCAP_SRC_IF_STRING  “rpcap://”    此两个宏在remote-ext.h里面定义。  
(2)详细描述  
下面列举出了能够被pcap_open()函数打开的格式:  
file://path_and_filename [打开一个本地文件] rpcap://devicename [打开本地机器上面的可以打开的设备,不使用rpcap协议] rpcap://host/devicename [打开远程机子上可以打开的设备] rpcap://host:port/devicename [打开远程机器上面选择的设备,用一个非标准端口作为rpcap] adaptername [打开一个本地适配器,kept for compability,不推荐] (NULL) [打开第一个本地适配器,kept for compability,不推荐]   Pcap_findalldevs_ex()允许的格式如下:  
file://folder/ [列出指定目录的所有文件] rpcap:// [列出本地的适配器] rpcap://host:port/ [列出远程机器上的可以列出的设备] 关于host和port参数,可以为数字或者字母。由于支持IPV6,它们可以是下面的格式:  
·         host (literal): e.g. host.foo.bar host (numeric IPv4): e.g. 10.11.12.13
host (numeric IPv4, IPv6 style): e.g. [10.11.12.13]
host (numeric IPv6): e.g. [1:2:3::4]   
port: can be either numeric (e.g. '80') or literal (e.g. 'http')
这里是一些例子: rpcap://host.foo.bar/devicename [everything literal, no port number] rpcap://host.foo.bar:1234/devicename [everything literal, with port number]
rpcap://10.11.12.13/devicename [IPv4 numeric, no port number]
rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number]
rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number]
rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number]
rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number]
rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number]
 转自:http://wotseb.bokee.com/1418997.html 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/qsycn/archive/2009/08/18/4457794.aspx