免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1566 | 回复: 0
打印 上一主题 下一主题

libpcap-第一课:获得设备列表 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-08-14 17:44 |只看该作者 |倒序浏览
第一课:获得设备列表



一个基本的WinPcap应用程序所需的第一件事情是获得合适的网络适配器。Libpcap/ Winpcap提供 pcap_findalldevs() 函数完成这个功能:这个函数返回一个相连的pcap_if结构的列表。列表的每一项包含关于适配器的复杂的信息。特别的,name和description域数据包含设备的名称和可读的描述。如下的代码提取设备列表,然后打印到屏幕上。如果没有发现适配器,则显示一个错误。
#include "pcap.h"
main
()
{
   
pcap_if_t
*alldevs;
   
pcap_if_t
*d;
    int i=0;
    char errbuf[
PCAP_ERRBUF_SIZE
];
   
    /* Retrieve the device list from the local machine */
    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);
    }
   
    /* Print the 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;
    }

    /* 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()
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
[/url]
sockaddr *  
[url=http://publishblog.blogchina.com/control/wpdpack_3_1_beta4/WpdPack/docs/html/structpcap__addr.html#o1]addr



a pointer to a struct sockaddr containing an address
[/url]
sockaddr *  
[url=http://publishblog.blogchina.com/control/wpdpack_3_1_beta4/WpdPack/docs/html/structpcap__addr.html#o2]netmask



if not NULL, a pointer to a struct sockaddr that contains the netmask corresponding to the address pointed to by addr.
[/url]
sockaddr *  
[url=http://publishblog.blogchina.com/control/wpdpack_3_1_beta4/WpdPack/docs/html/structpcap__addr.html#o3]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
[/url]
sockaddr *  
[url=http://publishblog.blogchina.com/control/wpdpack_3_1_beta4/WpdPack/docs/html/structpcap__addr.html#o4]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
[/url]

⑶函数说明
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  “
[url=http://publishblog.blogchina.com/control/blog/]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]

- 作者:
wotseb
2005年05月5日, 星期四 15:04
[url=javascript:void(keyit=window.open('http://blogmark.blogchina.com/jsp/key/quickaddkey.jsp?k='+encodeURI('第一课:获得设备列表')+'&u='+encodeURI('http://wotseb.blogchina.com/wotseb/1418997.html')+'&c='+encodeURI(''),'keyit','scrollbars=no,width=500,height=430,status=no,resizable=yes'));keyit.focus();]加入博采[/url]



本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/28528/showart_360037.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP