Windows下基于MSVC搭建Wintun開發(fā)環(huán)境 (qq.com)
前言
l有這么一種場景,某個windows下的應用程序底層數(shù)據(jù)接口基于以太網(wǎng),現(xiàn)在想修改為串口,那么一般來說需要修改該應用程序,添加對串口的支持,但是很多時候應用程序可能是第三方開發(fā)的并不能修改,有沒有在不修改應用程序的情況下實現(xiàn)兼容呢,
Wintun就提供了解決方案,Wintun可以創(chuàng)建虛擬網(wǎng)卡,提供IP層的數(shù)據(jù)鏈路,那么我們只需要使用Wintun創(chuàng)建虛擬網(wǎng)卡,將串口數(shù)據(jù)組包成指定協(xié)議層的包(UDP或者TCP/IP)等進行轉(zhuǎn)發(fā),那么該應用軟件可以訪問該虛擬網(wǎng)卡,無需任何修改。
由于wintun工作在IP層,所以需要根據(jù)實際情況去實現(xiàn)UDP或者TCP/IP等包的組包和解包。
l還有一種場景,我們希望在windows下進行嵌入式tcp/ip協(xié)議棧的源碼級別開發(fā)測試,那么就可以使用Wintun來模擬IP層的數(shù)據(jù)鏈路,而不直接訪問真實的MAC和PHY,基于此進行協(xié)議棧的開發(fā)調(diào)試,由于Wintun是IP層的,所以無法模擬數(shù)據(jù)鏈路層的部分,真實的場景是以太網(wǎng)控制器實現(xiàn)幀的收發(fā),而Wintun的是更上一層基于IP包的收發(fā),也就是從IP層截斷了,所以不能進行ARP等數(shù)據(jù)鏈路層的協(xié)議的分析調(diào)試。
準備
官網(wǎng)
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版本,都進行編譯
點擊項目名->重新生成構(gòu)建。
將wintun\\bin\\amd64和wintun\\bin\\x86下的wintun.dll分別放入
工程的輸出目錄\\x64\\Debug和\\Win32\\Debug下
右鍵點擊exe文件,以管理員身份運行(一定要管理員權(quán)限,否則出錯)
控制面板,網(wǎng)絡和共享中心,更改適配器設置,可以看到多了網(wǎng)卡Demo
命令行ipconfig可以看到
也可以ping通
基本API的使用
上面使用example進行了測試,為了熟悉API,可以自己寫一個測試代碼。
參考https://git.zx2c4.com/wintun/about/
加載庫,解析函數(shù)地址
LoadLibraryExW
GetProcAddress
先定義14個API函數(shù)的指針,
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;
}
解析函數(shù)地址,其他13個API類似
if ((*(FARPROC*)&WintunCreateAdapter = GetProcAddress(Wintun, "WintunCreateAdapter")) == NULL)
{
FreeLibrary(Wintun);
return -2;
}
以上為了方便理解分開了寫,example.c中用宏的形式更簡潔。
創(chuàng)建適配器
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 網(wǎng)絡,即子網(wǎng)掩碼為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);
}
發(fā)送包
Wintun工作在第三層IP層,發(fā)送的是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)
{
/* 使用接收到的數(shù)據(jù) */
/* 釋放 */
WintunReleaseReceivePacket(Session, Packet);
}
總結(jié)
Wintun提供了簡潔的接口,在用戶空間即可創(chuàng)建虛擬網(wǎng)卡,進行IP層的數(shù)據(jù)傳輸,基于此可以應用于很多應用場景,比如tcp/ip協(xié)議棧的移植,以太網(wǎng)和其他接口的轉(zhuǎn)換等。
審核編輯:湯梓紅
-
嵌入式
+關注
關注
5060文章
18980瀏覽量
302241 -
WINDOWS
+關注
關注
3文章
3523瀏覽量
88330 -
開發(fā)環(huán)境
+關注
關注
1文章
219瀏覽量
16570
發(fā)布評論請先 登錄
相關推薦
評論