Go to file
Simon Rozman 1170f56446 api: move files from root to wintun folder within Zip
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-10-31 10:15:15 +01:00
api api: use catalog file for signing certificate extraction 2020-10-31 10:15:15 +01:00
.clang-format Rewrite installer logic in C 2019-08-02 09:43:32 +00:00
.editorconfig Rewrite installer logic in C 2019-08-02 09:43:32 +00:00
.gitignore vcxproj: swap configuration and platform subfolder hierarchy 2020-10-30 16:51:00 +01:00
COPYING Initial commit 2019-03-22 16:52:31 -06:00
README.md api: upgrade ring management 2020-10-31 10:15:15 +01:00
undocumented.h Spin less and more efficiently 2019-08-04 07:06:50 +00:00
wintun.c Accept WoW64 clients 2020-10-30 16:50:58 +01:00
wintun.inf Annotate service control constants 2019-06-07 12:28:07 +02:00
wintun.proj api: move files from root to wintun folder within Zip 2020-10-31 10:15:15 +01:00
wintun.props api: add support for WoW64 2020-10-30 16:50:59 +01:00
wintun.rc Rewrite installer logic in C 2019-08-02 09:43:32 +00:00
wintun.sln api: installer: switch from MSM to ZIP distribution 2020-10-30 16:51:01 +01:00
wintun.vcxproj vcxproj: swap configuration and platform subfolder hierarchy 2020-10-30 16:51:00 +01:00
wintun.vcxproj.filters Use standard volatile semantics 2020-10-30 17:08:10 +01:00

Wintun Network Adapter

TUN Device Driver for Windows

This is a layer 3 TUN driver for Windows 7, 8, 8.1, and 10. Originally created for WireGuard, it is intended to be useful to a wide variety of projects that require layer 3 tunneling devices with implementations primarily in userspace.

Installation

Wintun is deployed as a platform-specific wintun.dll file. Install the wintun.dll file side-by-side with your application.

Usage

Include wintun.h file in your project and dynamically load the wintun.dll using LoadLibraryEx() and GetProcAddress().

Each function has its function typedef in wintun.h with additional usage documentation.

#include "wintun.h"

HMODULE Wintun = LoadLibraryExW(L"wintun.dll", NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR);
if (!Wintun)
    return GetLastError();
WINTUN_CREATE_ADAPTER_FUNC WintunCreateAdapter = (WINTUN_CREATE_ADAPTER_FUNC)GetProcAddress(Wintun, "WintunCreateAdapter");
WINTUN_DELETE_ADAPTER_FUNC WintunDeleteAdapter = (WINTUN_DELETE_ADAPTER_FUNC)GetProcAddress(Wintun, "WintunDeleteAdapter");

Adapter management

Adapters are grouped together in pools to allow various clients on the same machine. Each client vendor should pick own unique pool name.

Manage the network adapters using following functions:

  • WintunCreateAdapter() creates a new adapter.
  • WintunDeleteAdapter() deletes the adapter.
  • WintunEnumAdapters() enumerates all existing adapters.
  • WintunGetAdapter() gets existing adapter handle.
  • WintunFreeAdapter() frees adapter handle.
  • WintunGetAdapterDeviceObject() opens adapter device object.
  • WintunGetAdapterGUID() gets adapter GUID.
  • WintunGetAdapterLUID() gets adapter LUID.
  • WintunGetAdapterName() gets adapter name.
  • WintunSetAdapterName() sets adapter name.

Example:

DWORD Result;
WINTUN_ADAPTER_HANDLE Adapter;
BOOL RebootRequired;
Result = WintunCreateAdapter(L"com.contoso.myapp", "My VPN adapter", NULL, &Adapter, &RebootRequired);
if (Result != ERROR_SUCCESS)
    return Result;

Session management

Once adapter is created, use the following functions to start a session and transfer packets:

  • WintunStartSession() starts a session. One adapter may have only one session.
  • WintunEndSession() ends and frees the session.
  • WintunIsPacketAvailable() checks if there is a receive packet available.
  • WintunWaitForPacket() waits for a receive packet to become available.
  • WintunReceivePacket() receives one packet.
  • WintunReceiveRelease() releases internal buffer after client processed the receive packet.
  • WintunAllocateSendPacket() allocates memory for send packet.
  • WintunSendPacket() sends the packet.

Writing to and from rings

Reading packets from the adapter may be done as:

// TODO: Preallocate WINTUN_PACKET *Queue linked list with WINTUN_MAX_IP_PACKET_SIZE packets.
for (;;) {
    if (!WintunIsPacketAvailable(Session))
        WintunWaitForPacket(Session, INFINITE);
    for (WINTUN_PACKET *p = Queue; p && p->Size <= WINTUN_MAX_IP_PACKET_SIZE; p = p->Next)
        p->Size = DWORD_MAX;
    BYTE *Packet;
    DWORD PacketSize;
    DWORD Result = WintunReceivePacket(Session, &Packet, &PacketSize);
    if (Result != ERROR_SUCCESS)
        return Result;
    // TODO: Process packet.
    WintunReceiveRelease(Session, Packet);
}

It may be desirable to spin on WintunIsPacketAvailable() for some time under heavy use before waiting with WintunWaitForPacket(), in order to reduce latency.

Writing packets to the adapter may be done as:

// TODO: Calculate packet size.
BYTE *Packet;
DWORD Result = WintunAllocateSendPacket(Session, PacketSize, &Packet);
if (Result != ERROR_SUCCESS)
    return Result;
// TODO: Fill the packet.
WintunSendPacket(Session, Packet);

Misc functions

Other wintun.dll functions are:

  • WintunGetVersion() returns driver and NDIS major and minor versions.
  • WintunSetLogger() sets global logging callback function.

Example:

static BOOL CALLBACK
ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_ const WCHAR *LogLine)
{
    const WCHAR *Template;
    switch (Level)
    {
    case WINTUN_LOG_INFO: Template = L"[+] %s\n"; break;
    case WINTUN_LOG_WARN: Template = L"[-] %s\n"; break;
    case WINTUN_LOG_ERR:  Template = L"[!] %s\n"; break;
    default: return FALSE;
    }
    fwprintf(stderr, Template, LogLine);
    return TRUE;
}

WintunSetLogger(ConsoleLogger);

Building

Do not distribute drivers named "Wintun", as they will most certainly clash with official deployments. Instead distribute wintun.dll.

General requirements:

wintun.sln may be opened in Visual Studio for development and building. Be sure to run bcdedit /set testsigning on before to enable unsigned driver loading. The default run sequence (F5) in Visual Studio will build and insert Wintun.

License

The entire contents of this repository, including all documentation code, is "Copyright © 2018-2019 WireGuard LLC. All Rights Reserved." and is licensed under the GPLv2.