WEB开发网
开发学院操作系统windows 2008 深度剖析WinPcap之(七)——获得与释放网络适配器设... 阅读

深度剖析WinPcap之(七)——获得与释放网络适配器设备列表(1)

 2009-09-11 00:00:00 来源:WEB开发网   
核心提示: 函数首先调用add_or_find_if()函数给所有适配器详细信息的链表devlist添加该接口节点,但不带网络地址信息,深度剖析WinPcap之(七)——获得与释放网络适配器设备列表(1)(8),curdev局部变量指向该节点,然后调用packet.dll提供的PacketGetNetInf

函数首先调用add_or_find_if()函数给所有适配器详细信息的链表devlist添加该接口节点,但不带网络地址信息,curdev局部变量指向该节点。然后调用packet.dll提供的PacketGetNetInfoEx()函数,返回该节点的存储所有网络地址信息的链表。最后循环调用add_addr_to_list函数,向该节点添加网络地址信息链表的每个节点。

函数add_addr_to_list()给一个接口的pcap_if_t类型的节点添加一个网络地址信息,函数的原形如下:

static int add_addr_to_list(pcap_if_t *curdev,
struct sockaddr *addr,struct sockaddr *netmask,
struct sockaddr *broadaddr,struct sockaddr *dstaddr,
char *errbuf)

参数curdev表示描述一个适配器详细信息链表的节点,参数addr, netmask, broadaddr, dstaddr分别为该适配器一个接口的IP地址,网络掩码,广播地址,P2P目的地址。参数errbuf返回该函数的错误信息。

函数成功返回0,失败返回-1。

1.3.1.2     add_or_find_if函数

函数add_or_find_if在alldevs设备链表中中查找或添加一个节点,并返回该节点的信息。函数原型如下:

int add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
    u_int flags, const char *description, char *errbuf)

参数alldevs为描述所有适配器的链表,参数curdev_ret为所找到或添加的节点。参数name是接口的名字,参数flag表示接口的标识,比如是否支持回环功能。参数description是接口的描述。参数errbuf返回函数的错误信息。

函数成功返回0值,否则返回非0值。

函数的主要代码如下:

int add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
    u_int flags, const char *description, char *errbuf)
{
    pcap_t *p;
    pcap_if_t *curdev, *prevdev, *nextdev;
    int this_instance;
 
    /*在设备列表中存在该接口吗?*/
    for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
        if (strcmp(name, curdev->name) == 0)
            break;  /* 找到了该接口,跳出for循环 */
    }
 
    if (curdev == NULL) {
        /*没有找到该接口       
        *我们能打开该接口实现在线捕获吗?
*/
      
        p = pcap_open_live(name, 68, 0, 0, errbuf);
        if (p == NULL) {
            /*
             * No.  Don't bother including it.
             * Don't treat this as an error, though.
             */
            *curdev_ret = NULL;
            return (0);
        }
        pcap_close(p);
 
        /*
           *可以成功的打开该适配器,为它分配一个新的节点
         */
        curdev = malloc(sizeof(pcap_if_t));
        if (curdev == NULL) {
            //分配失败,返回
            return (-1);
        }
 
        /*
         * 填充该节点,除了网络地址信息
         */
        curdev->next = NULL;
        //设置适配器的名字
        curdev->name = strdup(name);
        …//处理错误的代码
 
//设置适配器的描述
        if (description != NULL) {
            //有接口的描述
            curdev->description = strdup(description);
            …//处理错误的代码
        } else {
            //没有接口的描述
            curdev->description = NULL;
        }
 
//设置适配器的网络地址列表,设置为NULL
        curdev->addresses = NULL;         
 
//设置PCAP_IF_接口标志
curdev->flags = 0;
        if (ISLOOPBACK(name, flags))
            curdev->flags |= PCAP_IF_LOOPBACK;
 
        /*把节点添加到合适的位置*/
 
        //首先,获取接口的实例数
        this_instance = get_instance(name);
 
        /*现在寻找实例号小于等于该新接口的实例号的最后一个接口
        *除了非回环接口,因此回环接口放置在链表的尾部。
         */
        prevdev = NULL;
        for (;;) {
            /*
             * 获得下一个接口。
             */
            if (prevdev == NULL) {
                /*下一个元素是第一个元素*/
                nextdev = *alldevs;
            } else
                nextdev = prevdev->next;
 
            /*我们在链表的尾部吗?*/
            if (nextdev == NULL) {
                /*是的,在"prevdev"之后添加一个新的条目*/
                break;
            }
 
            /*
*新的接口是一个非回环接口?下一个接口是一个回环接口吗?
             */
            if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
                (nextdev->flags & PCAP_IF_LOOPBACK)) {
                /*
*是的,
*我们应该把新的接口放置在"nextdev"之前,也就是在"prevdev"之后 
                 */
                break;
            }
 
            /*新接口的实例数小于下一个接口的实例数,
*并且新接口不是回环接口或下一个接口是一个回环接口?
            *
*(这两个回环检测的目的是确保我们不会把一个回环接口放置在任何一个
*不是回环的接口之前,并且我们总是把一个非回环接口放置在所有回环接口之前)
             */
            if (this_instance < get_instance(nextdev->name) &&
                (!(curdev->flags & PCAP_IF_LOOPBACK) ||
                   (nextdev->flags & PCAP_IF_LOOPBACK))) {
                /*
                 * 是的,我们应该新的条目放置在"nextdev"之前,
*也就是"prevdev"之后
                 */
                break;
            }
 
            prevdev = nextdev;
        }
 
        /* 插入到"nextdev"之前*/
        curdev->next = nextdev;
 
        /*
         *插入到"prevdev"之后 ——除非"prevdev"为null,
         * 这种情况下,这是第一个接口。
         */
        if (prevdev == NULL) {
            /*
             *传递回一个指向它的指针,并把"curdev"放置在"nextdev"之前。
             */
            *alldevs = curdev;
        } else
            prevdev->next = curdev;
    }
 
    *curdev_ret = curdev;
    return (0);
}

函数调用get_instance()函数获得接口的实例号,get_instance()函数的原型如下。

static int get_instance(const char *name)

函数从参数name中分析接口的实例号,如果name为"any"就返回INT_MAX最大的整数值。

1.3.2        pcap_findalldevs_ex函数

暂无

出处:http://eslxf.blog.51cto.com/918801/198579

上一页  3 4 5 6 7 8 

Tags:深度 剖析 WinPcap

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接