不知到现在hack小将们还有多少知道ipman这个东西,当时2000年左右在学校的内网大家玩的不亦乐乎。
年龄大了就开始怀旧,在我尝试了n种搜索方法之后,终于找到了当年我翻译的ipman的网卡驱动的说明。可惜的是nankai bbs几经变迁,在上面已经找不到我发的原文。只有一个转载了n层的版本:
http://nkbbs.org/cgi-bin/bbs/bbstcon?board=SysSafe&file=M.947127744.A
在这个叫做“烟雨漓江BBS站”的BBS以及四川大学“蓝色星空“站,居然今天也仍旧能找到别人转载的我写的关于vpacket.vxd的翻译(或者直接google "vpacket.vxd jxj"):
http://bbs.gxnu.cn/bbstcon.php?board=Programming&gid=1286
http://anphia.blog.lsxk.org/wForum/boardcon.php?bid=16&id=202&ftype=6
那时的人还是有节操,转载时不忘注明出处。
也贴在这里博大家一笑:
———————-我是原文分割线—————————————————-
这个,vxd有个说明文档,试着翻译了一下,不当之处请指出…. Windows 95下的直接网卡读写 澳大利亚堪培拉大学 信息科学和工程系 1997.8.6 概论
这个文档是VPACKET的说明.VPACKET是Windows 95下的一个虚拟设备驱动程序,它可以通过WIN32程序对安装在PC机上的任何网卡进行直接读写操作。直接网卡读写对编写网络管理程序和那些想实现自己的意图的编程者是十分有用的。这个驱动程序是P32编程环境[1]的一部分。P32是一个堪培拉大学用于操作系统和协议设计课程的WIN32程序包。
1.介绍
WIN32程序平台不支持低层次的直接的网卡操作.需要这种操作的程序(由于种种原因)必须用一个自定制的虚拟设备驱动程序(VXD).VXD提供一个在底层网络控制接口(NICS)和高层的WIN32程序间的一个服务接口.它的基本结构见图一. _________________ | 应用程序 | |_________________| /|\ | ———|——————————————– | _____\|/___________ | VPACKET | | VXD | |____________ ___| /|\ /|\ | _____\|/___________________________________________ | | | NDIS 3.10 | |_________________________________________________ | /|\ /|\ /|\ | | | ___\|/___ ___\|/___ ___\|/___ | NIC 0 | | NIC 0 | ……… | NIC N | |______ | |_______| |_______| 图一: 结构
一个程序必须首先用一个WIN32_API函数:CreateFile将此VXD装入内存,然后才能调用WIN32设备I/O控制函数来实现此VXD提供的功能。
2.关于接口抽象层
正像在图一中所看到的那样,这个虚拟设备驱动程序并没有直接面对已安装好的底层网络控制接口.在网络硬件和VXD之间有一个叫做NDIS 3.10的接口抽象层,使用这种接口抽象层的意图在于保护需要NIC接口的软件不受底层网络适配器特殊硬件细节的影响。因此这个VAPCKET VXD可以方便的同安装在不同机器上的任何NIC接口进行通讯,但这台机器上的网卡必须是支持NDIS的.注意,不同版本的NDIS对网卡的支持有些不同.尤其是微软的Dialup网卡(PPPMAC)不支持NDIS.因为一个普通的NDIS Send函数在这种网卡上传送不了任何数据。此外,这种网卡也不支持NDSI所支持的网卡所具有的数字统计硬件。
3.怎样装入一个VXD
一个WIN32程序使用一个特定的形式调用WIN32_API函数:CreateFile来装入VXD.下面的代码演示了如何装入VAPCKET VXD.
#include <windows.h>
HANDLE hVxD;
hVxD = CreateFile("\\\\.\\VPACKET.VXD", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_DELETE_ON_CLOSE, NULL); NULL);
if (hVxD == INVALID_HANDLE_VALUE)
return SYSERR;
第一个参数说明将要装入的VPACKET.VXD所在的目录.第六个参数应特别注意:它指明此驱动程序支持异步操作(FILE_FLAG_OVERLAPPED),同时也指出当VXD关闭时应当从内存中被释放(FILE_FLAG_DELETE_ON_CLOSE).
此函数要求异步操作立即返回到它的调用者那里,而不必非要等到操作被完成.应用程序必须用另外的方法(下面将要提到)来断定操作是否已经完成.
调用CreateFile函数所返回的句柄不是一个普通的文件句柄.实际上,程序就是通过它来完成设备驱动程序所提供的功能.
VPACKET VxD能被"打开"无数次,每次调用CreateFile函数将返回一个与其它各次不同的句柄.仅仅在第一次调用CreateFile函数时是真正的装入和执行此VxD,其它时刻调用CreateFile函数仅仅是返回一个新句柄而已.
VPACKET VxD的一个显著特征就是不需要安装或者设置,因此没有相应的inf文件.所有的设置工作在这个VxD被执行并被确定的绑定到一个或多个网络接口时被自动完成.
4.怎样从内存中卸载VxD
这个VxD能够被WIN32_API函数CloseHandle所卸载,释放从CreateFile函数所获得的句柄.假如此驱动程序被打开多次,则必须当所有的句柄都被释放时此VxD才被卸载.
5.怎样绑定到网络接口层
当VPACKET VxD被装入和执行时,它必须与一个特定的网络接口控制器发生联系,即绑定.绑定可以通过下面的Bind函数来完成.
int Bind(HANDLE hVxD, BYTE* inBuffer) {
HANDLE hEvent;
DWORD cbRet;
OVERLAPPED ovlp = {0,0,0,0,0};
int result;
int cbIn = 5;
hEvent = CreateEvent(0, TRUE, 0, NULL);
if (!hEvent)
return SYSERR;
ovlp.hEvent = hEvent;
result = DeviceIoControl(hVxD, IOCTL_PROTOCOL_BIND, IOCTL_PROTOCOL_BIND, inBuffer, cbIn, inBuffer, cbIn, &cbRet, &ovlp);
if (!result)
GetOverlappedResult(hVxD, &ovlp, &cbRet, TRUE);
CloseHandle(hEvent);
return OK;
}
第一个参数是先前调用的CreateFile函数所返回的句柄.第二个参数是命名句柄所将要绑定的适配器的字符串.这个字符串可以从Windows95的注册表的如下目录找到:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Class\Net
注意:对于每一个CreateFile函数所返回的句柄,应用程序再进行任何其他操作之前必须被绑定.
6.设备驱动API函数
一个WIN32程序可以用DeviceIoControl函数来调用设备驱动程序所提供的服务功能.上面所列出的Bind函数,第一个参数是
CreateFile函数所返回的句柄,第二个参数是下列函数代码之一:
IOCTL_PROTOCOL_QUERY_OID 得到详细的目标Object的ID
IOCTL_PROTOCOL_SET_OID 设置详细的目标ObjectID
IOCTL_PROTOCOL_STATISTICS 得到特定网卡(适配器)的状态
IOCTL_PROTOCOL_RESET 复位网卡(适配器)
IOCTL_PROTOCOL_READ 从网络上接受一个包
IOCTL_PROTOCOL_WRITE 在网上发送一个包
IOCTL_PROTOCOL_MACNAME 得到网卡驱动的名称
IOCTL_PROTOCOL_BIND 绑定VPACKET VXD到特定网卡(适配器)
使用以上操作的例子在附录中给出.
7.异步操作
Bind函数说明了异步操作是怎样在WIN32程序中实现的.WIN32_API函数CreateEvent被调用后的返回值存入OVERLAPPED结构的成员hEvent句柄.OVERLAPPED结构中剩下的成员被赋值为0.在调用DevIoControl函数时OVERLAPPED结构体的地址指针被作为最后一个参数传递给设备驱动程序.然后驱动程序便开始进行操作并返回一个值.当驱动程序完成所要求的操作时将发给一动程序便开始进行操作并返回一个值.当驱动程序完成所要求的操作时将发给一个特定的事件一个信号.与此同时WIN32程序可以完成一些其他事情.在绑定结束之前,Bind函数干不了更多的事情.因此在Bind的线程中仅仅调用了WIN32_API函数GetOverlappedResult.这个函数会阻止程序运行,直到特定事件收到操作完成的信号.(因为此函数最后一个参数恒为真实值TRUE).
参数3: 包含指定操作所需要的输入数据的缓冲区的地址
参数4: 上面提到的缓冲区大小
参数5: 保留指定操作的返回信息的缓冲区的地址
参数6: 上面提到的缓冲区大小
参数7: 一个双字(DWORD)变量的地址.这个变量表示驱动程序所返回的字节数.注意:这个变量也被用作GetOverlappedResult函数的参数.
当应用程序需要读出网卡所接受到的数据时,异步输入输出机制的强大优势将会更明显.应用程序(往往如此)不可能预先知道何时数据包将会从网上到达.因此程序可以完成一些其他的处理(如:处理Windows 95的消息)和通过调用GetOverlappedResult函数来检查是否有数据包到达.假如GetOverlappedResult函数返回值为FALSE,同时调用GetLastError函数返回ERROR_IO_PENDING,应用程序就可以知道没有数据包到达.假如GetOverlappedResult函数返回值为TRUE,则应用程序便知道有数据包到达,因此可以进行一些操作.
9.结论
这个VPACKET虚拟设备驱动程序提供给运行于Windows 95下的WIN32应用程序一种简单且有效的直接进行网络接口控制的机制.
在P32编程环境中,利用这个驱动程序,在Comer和Stevens[2]编写的代码基础之上实现了完全的TCP/IP协议.这个程序支持复合网络接口,完全的IP协议和入口功能.
作者的版本中还有一些附加特征:支持IP地址和端口列表.一个局域网中的主机可以使用另一个局域网中的一个可用的IP地址.所有局域网中的主机可以使用端对端(PPP)协议的IP地址连接到互联网(Internet)服务商.
10.参考及附注
[1] 有关信息可在以下网址获得: http://willow.canberra.edu.au/~chrisc/p32.html
[2] 有关信息在<<用TCP/IP进行网络互连>>第一卷,第二本,第二版查到,由 Prentice-Hall出版.1994.
[3] 关于VPACKET VXD的源代码,可以写信给作者. chrisc@fir.canberra.edu.au
[4] NAT32是Windows 95下的一个地址翻译包.可从下列网址查到有关信息: http://willow.canberra.edu.au/~chrisc/nat32.html http://willow.canberra.edu.au/~chrisc/nat32.html