Windows下基于MSVC搭建Wintun开发环境 (qq.com)
前言
l有这么一种场景,某个windows下的应用程序底层数据接口基于以太网,现在想修改为串口,那么一般来说需要修改该应用程序,添加对串口的支持,但是很多时候应用程序可能是第三方开发的并不能修改,有没有在不修改应用程序的情况下实现兼容呢,
Wintun就提供了解决方案,Wintun可以创建虚拟网卡,提供IP层的数据链路,那么我们只需要使用Wintun创建虚拟网卡,将串口数据组包成指定协议层的包(UDP或者TCP/IP)等进行转发,那么该应用软件可以访问该虚拟网卡,无需任何修改。
由于wintun工作在IP层,所以需要根据实际情况去实现UDP或者TCP/IP等包的组包和解包。
l还有一种场景,我们希望在windows下进行嵌入式tcp/ip协议栈的源码级别开发测试,那么就可以使用Wintun来模拟IP层的数据链路,而不直接访问真实的MAC和PHY,基于此进行协议栈的开发调试,由于Wintun是IP层的,所以无法模拟数据链路层的部分,真实的场景是以太网控制器实现帧的收发,而Wintun的是更上一层基于IP包的收发,也就是从IP层截断了,所以不能进行ARP等数据链路层的协议的分析调试。
准备
官网
https://www.wintun.net/
下载代码
git clone https://git.zx2c4.com/wintun
下载编译好的库
https://www.wintun.net/builds/wintun-0.14.1.zip
编译库
参考 https: / /git.zx2c4.com/wintun /about/#building
在自己的工程中使用
解压wintun-0.14.1.zip复制文件夹wintun到自己的工程目录
将下载的源码wintun\\example下的example.c复制到自己的工程中。
右键点击项目名->属性 设置相关属性,Window2和X86都同样设置。
设置头文件包含路径
$(MSBuildProjectDirectory)\\Src\\wintun\\include;
设置链接的库
iphlpapi.lib;kernel32.lib;ntdll.lib;ws2_32.lib;
设置输出路径
$(ProjectDir)$(Platform)\\$(Configuration)\\
切换X86和X64版本,都进行编译
点击项目名->重新生成构建。
将wintun\\bin\\amd64和wintun\\bin\\x86下的wintun.dll分别放入
工程的输出目录\\x64\\Debug和\\Win32\\Debug下
右键点击exe文件,以管理员身份运行(一定要管理员权限,否则出错)
控制面板,网络和共享中心,更改适配器设置,可以看到多了网卡Demo
命令行ipconfig可以看到
也可以ping通
基本API的使用
上面使用example进行了测试,为了熟悉API,可以自己写一个测试代码。
参考https://git.zx2c4.com/wintun/about/
加载库,解析函数地址
LoadLibraryExW
GetProcAddress
先定义14个API函数的指针,
static WINTUN_CREATE_ADAPTER_FUNC *WintunCreateAdapter;
static WINTUN_CLOSE_ADAPTER_FUNC *WintunCloseAdapter;
static WINTUN_OPEN_ADAPTER_FUNC *WintunOpenAdapter;
static WINTUN_GET_ADAPTER_LUID_FUNC *WintunGetAdapterLUID;
static WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC *WintunGetRunningDriverVersion;
static WINTUN_DELETE_DRIVER_FUNC *WintunDeleteDriver;
static WINTUN_SET_LOGGER_FUNC *WintunSetLogger;
static WINTUN_START_SESSION_FUNC *WintunStartSession;
static WINTUN_END_SESSION_FUNC *WintunEndSession;
static WINTUN_GET_READ_WAIT_EVENT_FUNC *WintunGetReadWaitEvent;
static WINTUN_RECEIVE_PACKET_FUNC *WintunReceivePacket;
static WINTUN_RELEASE_RECEIVE_PACKET_FUNC *WintunReleaseReceivePacket;
static WINTUN_ALLOCATE_SEND_PACKET_FUNC *WintunAllocateSendPacket;
static WINTUN_SEND_PACKET_FUNC *WintunSendPacket;
加载库
HMODULE Wintun = LoadLibraryExW(L"wintun.dll", NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!Wintun)
{
return -1;
}
解析函数地址,其他13个API类似
if ((*(FARPROC*)&WintunCreateAdapter = GetProcAddress(Wintun, "WintunCreateAdapter")) == NULL)
{
FreeLibrary(Wintun);
return -2;
}
以上为了方便理解分开了写,example.c中用宏的形式更简洁。
创建适配器
GUID ExampleGuid = { 0xdeadbabe, 0xcafe, 0xbeef, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef } };
WINTUN_ADAPTER_HANDLE Adapter = WintunCreateAdapter(L"Demo", L"Example", &ExampleGuid);
if (!Adapter)
{
FreeLibrary(Wintun);
return -3;
}
获取版本
DWORD Version = WintunGetRunningDriverVersion();
printf("Wintun v%u.%u loaded", (Version > > 16) & 0xff, (Version > > 0) & 0xff);
启动会话
MIB_UNICASTIPADDRESS_ROW AddressRow;
InitializeUnicastIpAddressEntry(&AddressRow); /* 单播IP地址 */
WintunGetAdapterLUID(Adapter, &AddressRow.InterfaceLuid); /* 获取LUID */
AddressRow.Address.Ipv4.sin_family = AF_INET;
AddressRow.Address.Ipv4.sin_addr.S_un.S_addr = htonl(ip); /* IP地址 16进制表示的xxx.xxx.xxx.xxx 高8位表示第一个xxx的16进制值 */
AddressRow.OnLinkPrefixLength = 24; /* /24 网络,即子网掩码为255.255.255.000 */
AddressRow.DadState = IpDadStatePreferred;
DWORD LastError = CreateUnicastIpAddressEntry(&AddressRow);
if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS)
{
printf("Failed to set IP address %d", LastError);
WintunCloseAdapter(Adapter);
FreeLibrary(Wintun);
}
WINTUN_SESSION_HANDLE Session = WintunStartSession(Adapter, 0x400000);
if (!Session)
{
printf("Failed to create adapter");
WintunCloseAdapter(Adapter);
FreeLibrary(Wintun);
}
发送包
Wintun工作在第三层IP层,发送的是IP包。
BYTE* Packet = WintunAllocateSendPacket(Session, len); /* 先分配空间 */
if (Packet)
{
memcpy(Packet,buffer,len);
WintunSendPacket(Session, Packet); /* Packet中包含了长度信息,所以不需要再添加长度 */
}
接收包
DWORD PacketSize;
BYTE* Packet = WintunReceivePacket(Session, &PacketSize);
if (Packet)
{
/* 使用接收到的数据 */
/* 释放 */
WintunReleaseReceivePacket(Session, Packet);
}
总结
Wintun提供了简洁的接口,在用户空间即可创建虚拟网卡,进行IP层的数据传输,基于此可以应用于很多应用场景,比如tcp/ip协议栈的移植,以太网和其他接口的转换等。
审核编辑:汤梓红
-
嵌入式
+关注
关注
5056文章
18955浏览量
301683 -
WINDOWS
+关注
关注
3文章
3515浏览量
88290 -
开发环境
+关注
关注
1文章
218浏览量
16566
发布评论请先 登录
相关推荐
评论