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_op为pcap_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;