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

更新时间:2024-01-25 16:21:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

深度剖析WinPcap之(八)——打开与关闭适配器(5) 2009-09-24 20:30:35 标签:WinPcap 打开 关闭 适配器 [推送到技术圈] 版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。

http://eslxf.blog.51cto.com/918801/205038

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) { } break;

p->dlt_list[0] = DLT_EN10MB; p->dlt_list[1] = DLT_DOCSIS; p->dlt_count = 2;

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_US

ER_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);

}

/*设置读取超时时间*/

PacketSetReadTimeout(p->adapter, p->md.timeout);

/*设置常规的NPF进行读取与设置过滤的操作句柄*/

/* 告诉驱动程序 只有存储了至少16K的数据后,才能复制数据*/ if(PacketSetMinToCopy(p->adapter,16000)==FALSE) { }

//错误,函数返回 …

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: }

函数首先调用wsockinit()函数初始化WinSock,然后调用packet.dll提供的函数PacketOpenAdapter()打开适配器。

接着调用packet.dll提供的函数PacketGetNetType()获取网络类型。根据网络类型设置链路类型。此处我们只分析常规的以太网捕获。

接下来调用packet.dll提供的函数PacketSetHwFilter()设置网络适pcap_cleanup_win32(p); return (PCAP_ERROR);

配器的过滤模式为混杂模式。

然后设置用户层与内核捕获数据的缓冲区大小分别为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()函数调用,调用该函数正确释放各种资源。

本文出自 “千江月” 博客,请务必保留此出处http://eslxf.blog.51cto.com/918801/205038

本文来源:https://www.bwwdw.com/article/il9w.html

Top