[原创]Winpcap4编程中Winsock的版本和IPv4与IPv6的兼容问题

发表于:2007-05-25来源:作者:点击数: 标签:编程Winpcap4版本原创winsock
在从 IPv4 到 IPv6 的升级过程中,有不少函数发生了变化。新版的 Winpcap 正在慢慢地从 IPv4 向 IPv6 迁移。在这个过程中,有不少函数已经被废弃。旧的例程在新版的 Winpcap 下无法使用,这其中也包括了一些著名的基于 winpcap/libpcap 的软件。比如 windump
在从 IPv4 到 IPv6 的升级过程中,有不少函数发生了变化。新版的 Winpcap 正在慢慢地从 IPv4 向 IPv6 迁移。在这个过程中,有不少函数已经被废弃。旧的例程在新版的 Winpcap 下无法使用,这其中也包括了一些著名的基于 winpcap/libpcap 的软件。比如 windump 和 snort for windows。作者在编程过程中收集了相关的资料,提出了解决方法。本文的最新版本和讨论保存在广州大学信息安全研究所 http://www.gzisi.com 网站的入侵检测文章部分。

很多程序员下载了 Winpcap 3.1 或更新的版本后,会发现原来自己运行得好好的程序突然不能使用了。而且其中涉及到一些相当重要的函数,比如 pcap_loop。 winpcap 对这些函数的修改使得很多基于它的应用程序(比如windump和snort)都将作出不小的改动。当然,还有你自己编写的代码……

以下是 Windows 本身的 Winsock 编程对此问题的影响。由于新版的 Winpcap 完全使用了新的 Winsock(支持IPv6),因此下列问题可能影响到每一个程序

这是新旧两版的 packet32.h 之间的差异

//Packet32.h
typedef struct npf_if_addr {
 struct sockaddr IPAddress; ///< IP address.
 struct sockaddr Su.netMask; ///< Netmask for that address.
 struct sockaddr Broadcast; ///< Broadcast address.
 //struct sockaddr_storage IPAddress; ///< IP address.
 //struct sockaddr_storage SubnetMask; ///< Netmask for that address.
 //struct sockaddr_storage Broadcast; ///< Broadcast address.
}npf_if_addr;

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/sockaddr_storage_2.asp

很多程序员仍然使用 Visual C++6 编译程序,不幸的是,VC++6中的 winsock2.h 太老了,它根本不认得 struct sockaddr_storage。因此,winpcap 自带的例程在 VC++6 下编译时会无情地抛出无数错误。事实上,该结构完全可以使用老的 sockaddr 代替。手工改动 packet32.h,将 sockaddr_storage 换成 sockaddr,编译将顺利通过。当然,这样的代码自然无法支持 IPv6 了。到目前为止,我没有找到在 VC++6 与Windows 2003中成功编译 IPv6 的例程。Windows 2000 的用户可以升级SDK,使自己的VC++6支持IPv6编程,但不幸的是这个SDK升级版检查操作系统的版本,不是2195就停止了安装,使我在 Windows XP 和 Win 2003 下无法安装。在作者写本文时,没有找到对 Win XP 和 Win 2003 的 IPv6 SDK。我没有安装那个巨达 106M 的 Windows 2003 开发升级包,但估计那个包中可能有支持 IPv6 开发所需的库和头文件。我也不排除对 for 2000 的SDK包做做手脚,提取其中的文件后能够成功运行的可能。因为 Microsoft Visual Studio.NET 2002/2003 已经对此提供了很好的支持。

躲过了 sockaddr_storage 一劫的朋友可能很快会遇到 socklen_t 和 getnameinfo 函数的错误。这两个函数包含在头文件 WS2TCPIP.H 中。很不幸,它也是一个 for IPv6 的函数,在VC++6中同样没有支持。编译时发生的错误如下:

--------------------Configuration: iflist - Win32 Debug--------------------
Compiling...
iflist.c
g:\security\ids\wpdpack\examples\iflist\iflist.c(151) : error C2065: 'socklen_t' : undeclared identifier
g:\security\ids\wpdpack\examples\iflist\iflist.c(151) : error C2146: syntax error : missing ';' before identifier 'sockaddrlen'
g:\security\ids\wpdpack\examples\iflist\iflist.c(151) : error C2065: 'sockaddrlen' : undeclared identifier
g:\security\ids\wpdpack\examples\iflist\iflist.c(160) : warning C4013: 'getnameinfo' undefined; assuming extern returning int
g:\security\ids\wpdpack\examples\iflist\iflist.c(166) : error C2065: 'NI_NUMERICHOST' : undeclared identifier
Error executing cl.exe.

iflist.exe - 4 error(s), 1 warning(s)

关于该函数,可以参考微软MSDN:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/getnameinfo_2.asp

同样,如果你不介意让程序仅能在 IPv4 上工作的话,可以用原来的函数 gethostbyname 代替。

原文转自:http://www.ltesting.net