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

1.4.2       pcap_open_live函数

函数首先 创建pcap_t结构体,设置捕获数据包的长度 设置网卡为混杂模式,设置读取超时时间,最后激活该已打开的捕捉实例。
函数的重要代码如下:
pcap_t *pcap_open_live(const char *source, int snaplen,
int promisc, int to_ms, char *errbuf)
{
    pcap_t *p;
    int status;
 
    /* 创建pcap_t结构体*/
    p = pcap_create(source, errbuf);
    if (p == NULL)
        return (NULL);
 
    /* 设置捕获数据包的长度*/
    status = pcap_set_snaplen(p, snaplen);
    if (status < 0)
        goto fail;
 
/* 设置混杂模式*/
    status = pcap_set_promisc(p, promisc);
    if (status < 0)
        goto fail;
 
/* 设置读取超时时间*/
    status = pcap_set_timeout(p, to_ms);
    if (status < 0)
        goto fail; 
 
   /* 如果使用pcap_open_live()函数,就设置为1*/
    p->oldstyle = 1;
   
/* 激活该已打开的捕捉实例p*/
status = pcap_activate(p);
    if (status < 0)
        goto fail;
    return (p);
fail:
    // 出错处理
   
}
 

1.4.2.1     pcap_create函数

函数首先 检查参数device是否为unicode字符串,如果是则转换为ASCII字符串 然后设置p->activate_op函数指针指向pcap_activate_win32函数。
函数的重要代码如下:
pcap_t *pcap_create(const char *device, char *ebuf)
{
    pcap_t *p;
 
/* 检查device是否为unicode字符串,如果是转换为ASCII字符串 */
    if (strlen(device) == 1)
    {
// 可能是unicode字符串
// 转换为ASCII字符串,
// 并把转换结果传递给pcap_create_common()函数        
        size_t length;
        char* deviceAscii;
 
        length = wcslen((wchar_t*)device);
 
        deviceAscii = (char*)malloc(length + 1);
       
        snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
        p = pcap_create_common(deviceAscii, ebuf);
        free(deviceAscii);
    }
    else
    {
        p = pcap_create_common(device, ebuf);
    }
   
   
    /* 设置p->activate_oppcap_activate_win32*/
    p->activate_op = pcap_activate_win32;
   
 
    return (p);
}
 

1.4.2.2     pcap_create_common函数

函数pcap_create_common()创建一个pcap_t结构体,并对结构体中的一些字段进行初始化,如果成功将返回指向pcap_t结构体内存的指针。 参数source是所要打开源的名称,参数 ebuf 存储函数的错误信息。
函数的重要代码如下:
pcap_t *pcap_create_common(const char *source, char *ebuf)
{
    pcap_t *p;
 
   /* 分配pcap_t的内存空间*/
    p = malloc(sizeof(*p));
    if (p == NULL) {
        // 分配失败,函数退出
    }
    memset(p, 0, sizeof(*p));
 
   /* p->opt.source复制源字符串*/
    p->opt.source = strdup(source);
    if (p->opt.source == NULL) {
        // 失败,函数退出
    }
 
    /*
* 默认为"不能设置rfmon模式"
* 如果被平台支持,可以设置该操作句柄,
* 使用所设置的例程检测设备是否支持。
    */
    p->can_set_rfmon_op = pcap_cant_set_rfmon;
 
    /*
* 一些操作只有在pcap_t是激活状态下才能执行
* 把这些操作句柄设为“不支持”的句柄,直到pcap_t被激活
    */
    p->read_op = (read_op_t)pcap_not_initialized;
    p->inject_op = (inject_op_t)pcap_not_initialized;
    p->setfilter_op = (setfilter_op_t)pcap_not_initialized;
    p->setdirection_op = (setdirection_op_t)pcap_not_initialized;
    p->set_datalink_op = (set_datalink_op_t)pcap_not_initialized;
    p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized;
    p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized;
    p->stats_op = (stats_op_t)pcap_not_initialized;
#ifdef WIN32
    p->setbuff_op = (setbuff_op_t)pcap_not_initialized;
    p->setmode_op = (setmode_op_t)pcap_not_initialized;
    p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
#endif
    p->cleanup_op = pcap_cleanup_live_common;
 
    /* 把一些只设为默认的*/
    pcap_set_timeout(p, 0);
    pcap_set_snaplen(p, 65535);
    p->opt.promisc = 0;
    p->opt.buffer_size = 0;
    return (p);
}
函数首先分配一个pcap_t结构体的内存空间,并对其清零。
然后给p->opt.source复制源字符串,然后设置p->can_set_rfmon_op操作句柄,使用所设置的例程pcap_cant_set_rfmon检测设备是否支持rfmon模式。
接着把一些只有在pcap_t是激活状态下才能执行的操作的句柄,设置为“不支持”的句柄pcap_not_initialized()
p->cleanup_op清除操作设置为pcap_cleanup_live_common()函数,使得与 pcap_open_live() 函数对应的 pcap_close() 函数调用,调用该函数正确释放各种资源。
最后把读取超时时间设为0,设置捕获数据包的长度为65535个字节,混杂模式p->opt.promisc设置为0,把缓冲区大小p->opt.buffer_size设为0
 
其中函数pcap_cant_set_rfmon()的实现如下
static int pcap_cant_set_rfmon(pcap_t *p _U_)
{
    return (0);
}
可见系统不支持rfmon模式。
函数pcap_not_initialized()的实现如下:
int pcap_not_initialized(pcap_t *pcap)
{
    /* 意味着“不初始化”*/
    return PCAP_ERROR_NOT_ACTIVATED;
}
 

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