深度剖析WinPcap之(八)――打开与关闭适配器(5)

1.4.2.3     pcap_activate_win32函数

在函数pcap_create()中把p->activate_op操作句柄设为 pcap_activate_win32()函数。函数pcap_activate_win32()为激活捕捉实例做各种准备工作。
函数的主要代码如下:
static int pcap_activate_win32(pcap_t *p)
{
    NetType type;
 
    /* 初始化WinSock*/
    wsockinit();
  
/* 调用packet.dll的函数PacketOpenAdapter()打开适配器*/
    p->adapter = PacketOpenAdapter(p->opt.source);
   
    if (p->adapter == NULL)
    {// 错误,函数返回
       
    }
   
    /* 调用packet.dll的函数PacketGetNetType()获取网络类型*/
    if(PacketGetNetType (p->adapter,&type) == FALSE)
    {
        // 错误,函数返回
       
    }
   
    /* 设置链路类型*/
    switch (type.LinkType)
    {
    case NdisMediumWan:
        p->linktype = DLT_EN10MB;
        break;
       
    case NdisMedium802_3:
        p->linktype = DLT_EN10MB;
        /*
         * 这大概是一个真正的以太网捕获;给它数据链路层类型链表设置为DLT_EN10MB DLT_DOCSIS,因此一个应用程序可以让你选择它的类型,以防万一正在捕获DOCSIS网络数据包,是由一个Cisco网线调制器终端系统发送到以太网上的(它不发送一个以太网协议头到线上,而是发送原始的DOCSIS数据帧到线上)。
         */
        p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
        /* 如果分配失败,仅留下空链表*/
        if (p->dlt_list != NULL) {
            p->dlt_list[0] = DLT_EN10MB;
            p->dlt_list[1] = DLT_DOCSIS;
            p->dlt_count = 2;
        }
        break;
       
   
 
    default:
        p->linktype = DLT_EN10MB;   /* 一个未知的适配器假定为以太网适配器*/
        break;
    }
 
    /* 设置网络适配器的过滤模式为混杂模式*/
    if (p->opt.promisc)
    {// 混杂模式
        if (PacketSetHwFilter(p->adapter,
NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
        {
            // 错误,函数返回
           
        }
    }
    else
    {// 非混杂模式
        if (PacketSetHwFilter(p->adapter,
NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE)
        {
            // 错误,函数返回
           
        }
    }
 
    /* 设置pcap_t结构体中的缓冲区大小*/
    p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
 
    /* 分配在捕获过程中使用的数据包结构体*/
    if((p->Packet = PacketAllocatePacket())==NULL)
    {
        // 错误,函数返回
           
    }
   
    if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD))
    {
    /*
     * 传统的适配器
     */
        /*
         * 如果缓冲区的大小不是显式的设定,默认为 WIN32_DEFAULT_USER_BUFFER_SIZE
         */
        if (p->opt.buffer_size == 0)
            p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
       // 设置内核NPF的缓冲区
        if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE)
        {
            // 错误,函数返回
           
        }
       
        p->buffer = (u_char *)malloc(p->bufsize);
        if (p->buffer == NULL)
        {
            // 错误,函数返回
           
        }
/* 初始化捕获过程中使用的数据包结构体*/
PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
       
        /* 告诉驱动程序 只有存储了至少16K的数据后,才能复制数据*/
        if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
        {
            // 错误,函数返回
           
        }
    }
   
    /* 设置读取超时时间*/
    PacketSetReadTimeout(p->adapter, p->md.timeout);
   
/* 设置常规的NPF进行读取与设置过滤的操作句柄*/
    p->read_op = pcap_read_win32_npf;
    p->setfilter_op = pcap_setfilter_win32_npf;
 
    p->setdirection_op = NULL;  /* 没有实现*/
   
p->inject_op = pcap_inject_win32;/* 发送单个数据包的操作*/
    p->set_datalink_op = NULL;  /* 不能改变数据链路层的类型*/
    p->getnonblock_op = pcap_getnonblock_win32;
    p->setnonblock_op = pcap_setnonblock_win32;
    p->stats_op = pcap_stats_win32;
    p->setbuff_op = pcap_setbuff_win32;
    p->setmode_op = pcap_setmode_win32;
    p->setmintocopy_op = pcap_setmintocopy_win32;
    p->cleanup_op = pcap_cleanup_win32;
 
    return (0);
bad:
    pcap_cleanup_win32(p);
    return (PCAP_ERROR);
}
函数首先调用wsockinit()函数初始化WinSock,然后调用packet.dll提供的函数PacketOpenAdapter()打开适配器。
接着调用packet.dll提供的函数PacketGetNetType()获取网络类型。根据网络类型设置链路类型。此处我们只分析常规的以太网捕获。
    接下来调用packet.dll提供的函数PacketSetHwFilter()设置网络适配器的过滤模式为混杂模式。
然后设置用户层与内核捕获数据的缓冲区大小分别为WIN32_DEFAULT_USER_BUFFER_SIZE(256KB)WIN32_DEFAULT_KERNEL_BUFFER_SIZE(1MB),并设置内核缓冲区,分配用户缓冲区,并进行初始化。
设置驱动程序只有存储了至少16K的数据后,才能复制数据到用户空间,设置读取超时时间。
设置NPF进行读取的操作句柄为pcap_read_win32_npf()函数与设置过滤的操作句柄为pcap_setfilter_win32_npf函数。
    设置发送单个数据包的操作句柄为pcap_inject_win32函数。设置下列函数句柄。   
    p->getnonblock_op = pcap_getnonblock_win32;
    p->setnonblock_op = pcap_setnonblock_win32;
    p->stats_op = pcap_stats_win32;
    p->setbuff_op = pcap_setbuff_win32;
    p->setmode_op = pcap_setmode_win32;
    p->setmintocopy_op = pcap_setmintocopy_win32;
    p->cleanup_op = pcap_cleanup_win32;
最后函数返回 。
 
其中函数wsockinit()主要调用WSAStartup()系统函数实现Winsocket的初始化。
p->cleanup_op清除操作设置为 pcap_cleanup_win32 () 函数,使得与pcap_open_live()函数对应的pcap_close()函数调用,调用该函数正确释放各种资源。

你可能感兴趣的:(职场,休闲,winpcap)