Skip to content

Replace ConvertInterfaceAliasToLuid with WintunGetAdapterLUID#20

Merged
ssrlive merged 2 commits into
tun2proxy:masterfrom
caobug:nsi
May 16, 2026
Merged

Replace ConvertInterfaceAliasToLuid with WintunGetAdapterLUID#20
ssrlive merged 2 commits into
tun2proxy:masterfrom
caobug:nsi

Conversation

@caobug

@caobug caobug commented May 15, 2026

Copy link
Copy Markdown
Contributor

Problem

Adapter::create / Adapter::open call ConvertInterfaceAliasToLuid(name)
right after WintunCreateAdapter returns. The alias is an NSI RW field
published asynchronously by NetCfg. WintunCreateAdapter's internal
WaitForInterface only waits on the PnP signal, so the alias lookup races
and returns ERROR_NOT_FOUND (1168) on real user machines.

Fix

Use WintunGetAdapterLUID (synchronous struct read, VOID return) for the
LUID. index / guid become lazy OnceLock with bounded retry on the
residual NSI race. Public API unchanged.

Both wintun's own example/example.c and wireguard-windows
(driver/driver_windows.go) use WintunGetAdapterLUID for this reason.

DWORD WINAPI ConvertInterfaceAliasToLuid( const WCHAR *alias, NET_LUID *luid )
{
    struct nsi_ndis_ifinfo_rw *data;
    DWORD err, count, i, len;
    NET_LUID *keys;

    TRACE( "(%s %p)\n", debugstr_w(alias), luid );

    if (!alias || !*alias || !luid) return ERROR_INVALID_PARAMETER;
    luid->Value = 0;
    len = wcslen( alias );

    err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&keys, sizeof(*keys),
                                  (void **)&data, sizeof(*data), NULL, 0, NULL, 0, &count, 0 );
    if (err) return err;

    err = ERROR_INVALID_PARAMETER;
    for (i = 0; i < count; i++)
    {
        if (data[i].alias.Length == len * 2 && !memcmp( data[i].alias.String, alias, len * 2 ))
        {
            luid->Value = keys[i].Value;
            err = ERROR_SUCCESS;
            break;
        }
    }
    NsiFreeTable( keys, data, NULL, NULL );
    return err;
}

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a real-world race during Adapter::create / Adapter::open by avoiding ConvertInterfaceAliasToLuid(name) (which can fail while the interface alias is asynchronously published) and instead deriving the adapter LUID directly from the Wintun handle via WintunGetAdapterLUID. It also changes GUID and interface index resolution to be lazy and retried to reduce residual NSI timing issues while keeping the public API surface unchanged.

Changes:

  • Replace alias→LUID lookup with WintunGetAdapterLUID in Adapter::create and Adapter::open.
  • Make adapter GUID and interface index lazy (OnceLock) with bounded retry on ERROR_NOT_FOUND NSI races.
  • Remove the now-unused alias_to_luid helper and its Win32 import.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/ffi.rs Removes ConvertInterfaceAliasToLuid usage and deletes alias_to_luid helper.
src/adapter.rs Uses WintunGetAdapterLUID, adds lazy GUID/index resolution with retry helper, and updates call sites to use get_guid().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/adapter.rs Outdated
Comment thread src/adapter.rs Outdated
Comment thread src/adapter.rs Outdated
@ssrlive ssrlive merged commit bd3c07d into tun2proxy:master May 16, 2026
6 checks passed
@ssrlive

ssrlive commented May 16, 2026

Copy link
Copy Markdown
Member

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants