深度剖析WinPcap之(七)——获得与释放网络适配器设备列表(1)
2009-09-11 00:00:00 来源:WEB开发网首先, pcap_findalldevs_ex函数和其他libpcap函数一样,有一个 errbuf 参数。一旦发生错误,这个参数将会被libpcap写入字符串类型的错误信息。
第二要记住,不是所有的操作系统都支持libpcap提供的网络程序接口,因此,如果想编写一个可移植的应用程序,就必须考虑在什么情况下, description 是 null。在本程序中遇到这种情况时,会打印提示语句"No description available"。
最后要记住,当完成了设备列表的使用,要调用 pcap_freealldevs() 函数将其占用的内存资源释放。
在某台WinXP的电脑上,运行该程序得到的结果是:
1. \Device\NPF_{4E273621-5161-46C8-895A-48D0E52A0B83} (Realtek RTL8029(AS) Ethernet Adapter)
2. \Device\NPF_{5D24AE04-C486-4A96-83FB-8B5EC6C7F430} (3Com EtherLink PCI)
正如看到的,Windows平台下的网络适配器的名称读起来相当容易,可见,解释性的描述是很有帮助的。
1.3 wpcap.dll中相应函数接口的实现
1.3.1 pcap_findalldevs函数
wpcap\libpcap\fad-win32.c(219): 218-327
参数alldevsp返回所找到的适配器列表,参数errbuf返回错误信息。
int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
{
pcap_if_t *devlist = NULL;
int ret = 0;
const char *desc;
char *AdaptersName;
ULONG NameLength;
char *name;
// PacketGetAdapterNames 是packet.dll中提供的函数,获取一个可用网络适配器的列表与它们的描述
//NameLength返回存储适配器列表所需的字节数
if (!PacketGetAdapterNames(NULL, &NameLength))
{
//获取字节数失败,处理错误,程序退出
…
}
if (NameLength > 0)
AdaptersName = (char*) malloc(NameLength);//分配存储适配器列表所需内存
else
{
*alldevsp = NULL;
return 0;
}
if (AdaptersName == NULL)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
return (-1);
}
if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {//获取可用网络适配器列表
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"PacketGetAdapterNames: %s",
pcap_win32strerror());
free(AdaptersName);
return (-1);
}
/* "PacketGetAdapterNames()"返回一个以空字符结尾的ASCII字符串,该字符串存储接口名列表,以一个空字符结尾,其后为一个以空字符结尾的ASCII字符串,该字符串存储接口描述列表,以一个空字符结尾。 这意味着在第一个列表的末尾有两个ASCII空字符。*/
/*查找第一个列表的末尾,那是第二个列表的开始*/
desc = &AdaptersName[0];
while (*desc != '\0' || *(desc + 1) != '\0') //查找第一个两个紧连着的空字符(‘\0\0’)
desc++;
/* 找到了 - "desc"指向接口名列表末尾的两个空字符的第一个。因此描述列表的第一个字节在后面两个字节的位置。*/
desc += 2;
/*循环遍历第一个列表中的所有元素*/
name = &AdaptersName[0];
while (*name != '\0') {
/*为每个接口在devlist链表中添加一个节点*/
if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {
/*操作失败*/
ret = -1;
break;
}
name += strlen(name) + 1;
desc += strlen(desc) + 1;
}
if (ret != -1) {
/*至此,没有任何错误,做任何特定平台的操作添加设备*/
/* pcap_platform_finddevs是 pcap_findalldevs()的内部接口
pcap_platform_finddevs()是一个依赖平台的例程,添加没有被“标准”机制"(SIOCGIFCONF,"getifaddrs()",等)找到的设备。
*/
if (pcap_platform_finddevs(&devlist, errbuf) < 0)
ret = -1;
}
if (ret == -1) {
//发生错误,释放所构建的列表devlist
if (devlist != NULL) {
pcap_freealldevs(devlist);
devlist = NULL;
}
}
*alldevsp = devlist; //返回最终的适配器列表
free(AdaptersName); //释放存储适配器列表所的内存
return (ret);
}
- ››深度解释攻击linux服务器的四种级别
- ››剖析java.util.concurrent锁
- ››剖析Android智能手机系统的更多功能
- ››深度分析地方社区网站的内容定位
- ››剖析Windows Azure Platform框架与组成
- ››剖析使用 ObjectOutputStream 可能引起的内存泄漏...
- ››剖析EWebEditor编辑器漏洞攻击案例
- ››剖析开源云:构建 Infrastructure as a Service 块...
- ››深度剖析 Android 和 iPhone OS
- ››深度分析:HTML5能否成为Flash终结者
- ››深度挖掘 更多Windows 7快捷模式
- ››深度挖掘 Windows 7快捷模式
更多精彩
赞助商链接