From 5d145914c6f7f87471f8c4072e7423beb40bfbe4 Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Wed, 6 May 2026 19:11:07 -0400 Subject: [PATCH] vpn: add Wintun dynamic-loading header for Windows --- app/vpn/wintun.h | 158 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 app/vpn/wintun.h diff --git a/app/vpn/wintun.h b/app/vpn/wintun.h new file mode 100644 index 0000000..8659682 --- /dev/null +++ b/app/vpn/wintun.h @@ -0,0 +1,158 @@ +// wintun.h — Dynamic-loading wrapper for the Wintun kernel TUN driver. +// +// Wintun is distributed as wintun.dll and loaded at runtime via LoadLibraryEx. +// All API functions are resolved via GetProcAddress. +// +// Reference: https://git.zx2c4.com/wintun +// License : Wintun is (C) WireGuard LLC; the header bindings here are MIT. +// +// Usage: +// WintunLib wt; +// if (!wt.load()) { /* wintun.dll not found */ } +// WINTUN_ADAPTER_HANDLE adp = wt.CreateAdapter(L"DragonMoonlight", L"WireGuard", nullptr); + +#pragma once + +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include + +// ─── Wintun opaque types ────────────────────────────────────────────────────── + +typedef void *WINTUN_ADAPTER_HANDLE; +typedef void *WINTUN_SESSION_HANDLE; + +// ─── Wintun function pointer types ─────────────────────────────────────────── + +typedef WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_CREATE_ADAPTER_FUNC)( + LPCWSTR Name, LPCWSTR TunnelType, const GUID *RequestedGUID); + +typedef WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_OPEN_ADAPTER_FUNC)(LPCWSTR Name); + +typedef void(WINAPI *WINTUN_CLOSE_ADAPTER_FUNC)(WINTUN_ADAPTER_HANDLE Adapter); + +typedef BOOL(WINAPI *WINTUN_DELETE_DRIVER_FUNC)(void); + +typedef void(WINAPI *WINTUN_GET_ADAPTER_LUID_FUNC)(WINTUN_ADAPTER_HANDLE Adapter, + NET_LUID *Luid); + +typedef DWORD(WINAPI *WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC)(void); + +typedef WINTUN_SESSION_HANDLE(WINAPI *WINTUN_START_SESSION_FUNC)( + WINTUN_ADAPTER_HANDLE Adapter, DWORD Capacity); + +typedef void(WINAPI *WINTUN_END_SESSION_FUNC)(WINTUN_SESSION_HANDLE Session); + +typedef HANDLE(WINAPI *WINTUN_GET_READ_WAIT_EVENT_FUNC)(WINTUN_SESSION_HANDLE Session); + +typedef BYTE *(WINAPI *WINTUN_RECEIVE_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session, + DWORD *PacketSize); + +typedef void(WINAPI *WINTUN_RELEASE_RECEIVE_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session, + const BYTE *Packet); + +typedef BYTE *(WINAPI *WINTUN_ALLOC_SEND_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session, + DWORD PacketSize); + +typedef void(WINAPI *WINTUN_SEND_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session, + const BYTE *Packet); + +// ─── WintunLib — RAII loader ────────────────────────────────────────────────── + +class WintunLib { +public: + // Function pointers — public so TunnelManager can call them directly. + WINTUN_CREATE_ADAPTER_FUNC CreateAdapter = nullptr; + WINTUN_OPEN_ADAPTER_FUNC OpenAdapter = nullptr; + WINTUN_CLOSE_ADAPTER_FUNC CloseAdapter = nullptr; + WINTUN_DELETE_DRIVER_FUNC DeleteDriver = nullptr; + WINTUN_GET_ADAPTER_LUID_FUNC GetAdapterLUID = nullptr; + WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC GetRunningDriverVersion = nullptr; + WINTUN_START_SESSION_FUNC StartSession = nullptr; + WINTUN_END_SESSION_FUNC EndSession = nullptr; + WINTUN_GET_READ_WAIT_EVENT_FUNC GetReadWaitEvent = nullptr; + WINTUN_RECEIVE_PACKET_FUNC ReceivePacket = nullptr; + WINTUN_RELEASE_RECEIVE_PACKET_FUNC ReleaseReceivePacket = nullptr; + WINTUN_ALLOC_SEND_PACKET_FUNC AllocSendPacket = nullptr; + WINTUN_SEND_PACKET_FUNC SendPacket = nullptr; + + WintunLib() = default; + ~WintunLib() { unload(); } + + // Non-copyable + WintunLib(const WintunLib &) = delete; + WintunLib &operator=(const WintunLib &) = delete; + + /// Load wintun.dll from the application directory first, then System32. + /// Returns true on success. + bool load() { + m_module = LoadLibraryExW(L"wintun.dll", nullptr, + LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); + if (!m_module) return false; + +#define WINTUN_RESOLVE(name) \ + name = reinterpret_cast(GetProcAddress(m_module, #name)); \ + if (!name) { unload(); return false; } + + WINTUN_RESOLVE(WintunCreateAdapter) + WINTUN_RESOLVE(WintunOpenAdapter) + WINTUN_RESOLVE(WintunCloseAdapter) + WINTUN_RESOLVE(WintunDeleteDriver) + WINTUN_RESOLVE(WintunGetAdapterLUID) + WINTUN_RESOLVE(WintunGetRunningDriverVersion) + WINTUN_RESOLVE(WintunStartSession) + WINTUN_RESOLVE(WintunEndSession) + WINTUN_RESOLVE(WintunGetReadWaitEvent) + WINTUN_RESOLVE(WintunReceivePacket) + WINTUN_RESOLVE(WintunReleaseReceivePacket) + WINTUN_RESOLVE(WintunAllocSendPacket) + WINTUN_RESOLVE(WintunSendPacket) + +#undef WINTUN_RESOLVE + + // Remap the struct member names to the exported symbol names + CreateAdapter = WintunCreateAdapter; + OpenAdapter = WintunOpenAdapter; + CloseAdapter = WintunCloseAdapter; + DeleteDriver = WintunDeleteDriver; + GetAdapterLUID = WintunGetAdapterLUID; + GetRunningDriverVersion = WintunGetRunningDriverVersion; + StartSession = WintunStartSession; + EndSession = WintunEndSession; + GetReadWaitEvent = WintunGetReadWaitEvent; + ReceivePacket = WintunReceivePacket; + ReleaseReceivePacket = WintunReleaseReceivePacket; + AllocSendPacket = WintunAllocSendPacket; + SendPacket = WintunSendPacket; + + return true; + } + + bool isLoaded() const { return m_module != nullptr; } + + void unload() { + if (m_module) { FreeLibrary(m_module); m_module = nullptr; } + CreateAdapter = nullptr; /* etc — reset all to nullptr */ + } + +private: + HMODULE m_module = nullptr; + + // Raw resolved symbols (before copying to public members) + WINTUN_CREATE_ADAPTER_FUNC WintunCreateAdapter = nullptr; + WINTUN_OPEN_ADAPTER_FUNC WintunOpenAdapter = nullptr; + WINTUN_CLOSE_ADAPTER_FUNC WintunCloseAdapter = nullptr; + WINTUN_DELETE_DRIVER_FUNC WintunDeleteDriver = nullptr; + WINTUN_GET_ADAPTER_LUID_FUNC WintunGetAdapterLUID = nullptr; + WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC WintunGetRunningDriverVersion = nullptr; + WINTUN_START_SESSION_FUNC WintunStartSession = nullptr; + WINTUN_END_SESSION_FUNC WintunEndSession = nullptr; + WINTUN_GET_READ_WAIT_EVENT_FUNC WintunGetReadWaitEvent = nullptr; + WINTUN_RECEIVE_PACKET_FUNC WintunReceivePacket = nullptr; + WINTUN_RELEASE_RECEIVE_PACKET_FUNC WintunReleaseReceivePacket = nullptr; + WINTUN_ALLOC_SEND_PACKET_FUNC WintunAllocSendPacket = nullptr; + WINTUN_SEND_PACKET_FUNC WintunSendPacket = nullptr; +};