Big code refactoring #10

Merged
Sirherobrine23 merged 15 commits from code_refactoring into main 2024-03-15 04:08:27 +00:00
17 changed files with 1462 additions and 14 deletions
Showing only changes of commit 1554e08ae9 - Show all commits

@ -26,6 +26,18 @@
"${workspaceFolder}/**", "${workspaceFolder}/**",
"${workspaceFolder}/addon" "${workspaceFolder}/addon"
] ]
},
{
"name": "Win32",
"includePath": [
"${env:appdata}/../.cache/rebory/latest/node/include/node",
"${workspaceFolder}/node_modules/node-addon-api",
"${workspaceFolder}/addon"
],
"defines": [],
"intelliSenseMode": "windows-msvc-x64",
"cStandard": "c17",
"cppStandard": "c++17"
} }
], ],
"version": 4 "version": 4

28
.vscode/settings.json vendored

@ -89,6 +89,32 @@
"unordered_map": "cpp", "unordered_map": "cpp",
"variant": "cpp", "variant": "cpp",
"vector": "cpp", "vector": "cpp",
"algorithm": "cpp" "algorithm": "cpp",
"bit": "cpp",
"charconv": "cpp",
"codecvt": "cpp",
"format": "cpp",
"forward_list": "cpp",
"functional": "cpp",
"iomanip": "cpp",
"iterator": "cpp",
"list": "cpp",
"stop_token": "cpp",
"thread": "cpp",
"utility": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp"
} }
} }

@ -5,6 +5,8 @@ std::string getWireguardVersion() {
return ""; return "";
} }
std::string driveLoad(std::map<std::string, std::string> load) {}
void IpManeger::SetInInterface(std::string interfaceName) { void IpManeger::SetInInterface(std::string interfaceName) {
throw std::string("Use userspace module"); throw std::string("Use userspace module");
} }

@ -26,6 +26,10 @@ std::string getWireguardVersion() {
return "Kernel"; return "Kernel";
} }
std::string driveLoad(std::map<std::string, std::string> load) {
throw std::string("Use userspace module");
}
void WireguardDevices::getInterfaces() { void WireguardDevices::getInterfaces() {
size_t len; char *device_name, *devicesList = wg_list_device_names(); size_t len; char *device_name, *devicesList = wg_list_device_names();

@ -3,6 +3,21 @@
#include <napi.h> #include <napi.h>
Napi::Object StartAddon(const Napi::Env env, const Napi::Object exports) { Napi::Object StartAddon(const Napi::Env env, const Napi::Object exports) {
std::map<std::string, std::string> LoadConfig;
const Napi::Array keysOnLoadsNames = exports.GetPropertyNames();
for (unsigned int keyIndex = 0; keyIndex < keysOnLoadsNames.Length(); keyIndex++) {
if (!(exports.Get(keysOnLoadsNames[keyIndex]).IsString())) continue;
LoadConfig[keysOnLoadsNames[keyIndex].ToString().Utf8Value()] = exports.Get(keysOnLoadsNames[keyIndex]).ToString().Utf8Value();
}
#ifdef _WIN32
std::string statusLoading = driveLoad(LoadConfig);
if (!!(statusLoading.length())) {
Napi::Error::New(env, statusLoading).ThrowAsJavaScriptException();
return exports;
}
#endif
const Napi::Object Constants = Napi::Object::New(env), Userspace = Napi::Object::New(env); const Napi::Object Constants = Napi::Object::New(env), Userspace = Napi::Object::New(env);
if (getWireguardVersion().length() > 0) Constants.Set("driveVersion", getWireguardVersion()); if (getWireguardVersion().length() > 0) Constants.Set("driveVersion", getWireguardVersion());
Userspace.Set("driveVersion", WireguardUserspace::getVersion()); Userspace.Set("driveVersion", WireguardUserspace::getVersion());

@ -10,6 +10,7 @@ extern const int wgKeyLength;
extern const int Base64WgKeyLength; extern const int Base64WgKeyLength;
std::string getWireguardVersion(); std::string getWireguardVersion();
std::string driveLoad(std::map<std::string, std::string> load);
class WireguardDevices : public std::vector<std::string> { class WireguardDevices : public std::vector<std::string> {
public: public:
@ -32,13 +33,52 @@ class WireguardDevices : public std::vector<std::string> {
} }
}; };
typedef struct IpReference { typedef struct {
std::string Address; std::string Address, Subnet;
int Mask, Proto; int Mask, Proto;
}; } IpReference;
/** Maneger Interface IPs */ /** Maneger Interface IPs */
class IpManeger : public std::vector<std::string> { class IpManeger : public std::vector<std::string> {
private:
std::string getSubNet4(int Mask) {
switch (Mask) {
case 1: return "128.0.0.0";
case 2: return "192.0.0.0";
case 3: return "224.0.0.0";
case 4: return "240.0.0.0";
case 5: return "248.0.0.0";
case 6: return "252.0.0.0";
case 7: return "254.0.0.0";
case 8: return "255.0.0.0";
case 9: return "255.128.0.0";
case 10: return "255.192.0.0";
case 11: return "255.224.0.0";
case 12: return "255.240.0.0";
case 13: return "255.248.0.0";
case 14: return "255.252.0.0";
case 15: return "255.254.0.0";
case 16: return "255.255.0.0";
case 17: return "255.255.128.0";
case 18: return "255.255.192.0";
case 19: return "255.255.224.0";
case 20: return "255.255.240.0";
case 21: return "255.255.248.0";
case 22: return "255.255.252.0";
case 23: return "255.255.254.0";
case 24: return "255.255.255.0";
case 25: return "255.255.255.128";
case 26: return "255.255.255.192";
case 27: return "255.255.255.224";
case 28: return "255.255.255.240";
case 29: return "255.255.255.248";
case 30: return "255.255.255.252";
case 31: return "255.255.255.254";
default:
case 32: return "255.255.255.255";
}
}
public: public:
void SetInInterface(std::string interfaceName); void SetInInterface(std::string interfaceName);
void GetInInterface(std::string interfaceName); void GetInInterface(std::string interfaceName);
@ -56,6 +96,7 @@ class IpManeger : public std::vector<std::string> {
if (!isIPv6 && xTop.Mask > 32) throw std::string("Set valid mask to ipv4 address!"); if (!isIPv6 && xTop.Mask > 32) throw std::string("Set valid mask to ipv4 address!");
} }
xTop.Proto = isIPv6 ? 6 : 4; xTop.Proto = isIPv6 ? 6 : 4;
if (!isIPv6) xTop.Subnet = this->getSubNet4(xTop.Mask);
this->push_back(xTop.Address.append("/").append(std::to_string(xTop.Mask))); this->push_back(xTop.Address.append("/").append(std::to_string(xTop.Mask)));
} }
@ -67,6 +108,7 @@ class IpManeger : public std::vector<std::string> {
nTop.Address = ipAddrr->substr(0, maskStart); nTop.Address = ipAddrr->substr(0, maskStart);
nTop.Mask = std::stoi(ipAddrr->substr(maskStart+1).c_str()); nTop.Mask = std::stoi(ipAddrr->substr(maskStart+1).c_str());
nTop.Proto = (nTop.Address.find(":") != std::string::npos) ? 6 : 4; nTop.Proto = (nTop.Address.find(":") != std::string::npos) ? 6 : 4;
if (nTop.Proto == 6) nTop.Subnet = this->getSubNet4(nTop.Mask);
xTops.push_back(nTop); xTops.push_back(nTop);
} }
return xTops; return xTops;

84
addon/win/LICENSE.txt Normal file

@ -0,0 +1,84 @@
Prebuilt Binaries License
-------------------------
1. DEFINITIONS. "Software" means the precise contents of the "wireguard.dll"
files that are included in the .zip file that contains this document as
downloaded from download.wireguard.com.
2. LICENSE GRANT. WireGuard LLC grants to you a non-exclusive and
non-transferable right to use Software for lawful purposes under certain
obligations and limited rights as set forth in this agreement.
3. RESTRICTIONS. Software is owned and copyrighted by WireGuard LLC. It is
licensed, not sold. Title to Software and all associated intellectual
property rights are retained by WireGuard. You must not:
a. reverse engineer, decompile, disassemble, extract from, or otherwise
modify the Software;
b. modify or create derivative work based upon Software in whole or in
parts, except insofar as only the API interfaces of the "wireguard.h" file
distributed alongside the Software (the "Permitted API") are used;
c. remove any proprietary notices, labels, or copyrights from the Software;
d. resell, redistribute, lease, rent, transfer, sublicense, or otherwise
transfer rights of the Software without the prior written consent of
WireGuard LLC, except insofar as the Software is distributed alongside
other software that uses the Software only via the Permitted API;
e. use the name of WireGuard LLC, the WireGuard project, the WireGuard
project, or the names of its contributors to endorse or promote products
derived from the Software without specific prior written consent.
4. LIMITED WARRANTY. THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF
ANY KIND. WIREGUARD LLC HEREBY EXCLUDES AND DISCLAIMS ALL IMPLIED OR
STATUTORY WARRANTIES, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE, QUALITY, NON-INFRINGEMENT, TITLE, RESULTS,
EFFORTS, OR QUIET ENJOYMENT. THERE IS NO WARRANTY THAT THE PRODUCT WILL BE
ERROR-FREE OR WILL FUNCTION WITHOUT INTERRUPTION. YOU ASSUME THE ENTIRE
RISK FOR THE RESULTS OBTAINED USING THE PRODUCT. TO THE EXTENT THAT
WIREGUARD LLC MAY NOT DISCLAIM ANY WARRANTY AS A MATTER OF APPLICABLE LAW,
THE SCOPE AND DURATION OF SUCH WARRANTY WILL BE THE MINIMUM PERMITTED UNDER
SUCH LAW. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR
A PARTICULAR PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE
EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
5. LIMITATION OF LIABILITY. To the extent not prohibited by law, in no event
WireGuard LLC or any third-party-developer will be liable for any lost
revenue, profit or data or for special, indirect, consequential, incidental
or punitive damages, however caused regardless of the theory of liability,
arising out of or related to the use of or inability to use Software, even
if WireGuard LLC has been advised of the possibility of such damages.
Solely you are responsible for determining the appropriateness of using
Software and accept full responsibility for all risks associated with its
exercise of rights under this agreement, including but not limited to the
risks and costs of program errors, compliance with applicable laws, damage
to or loss of data, programs or equipment, and unavailability or
interruption of operations. The foregoing limitations will apply even if
the above stated warranty fails of its essential purpose. You acknowledge,
that it is in the nature of software that software is complex and not
completely free of errors. In no event shall WireGuard LLC or any
third-party-developer be liable to you under any theory for any damages
suffered by you or any user of Software or for any special, incidental,
indirect, consequential or similar damages (including without limitation
damages for loss of business profits, business interruption, loss of
business information or any other pecuniary loss) arising out of the use or
inability to use Software, even if WireGuard LLC has been advised of the
possibility of such damages and regardless of the legal or quitable theory
(contract, tort, or otherwise) upon which the claim is based.
6. TERMINATION. This agreement is affected until terminated. You may
terminate this agreement at any time. This agreement will terminate
immediately without notice from WireGuard LLC if you fail to comply with
the terms and conditions of this agreement. Upon termination, you must
delete Software and all copies of Software and cease all forms of
distribution of Software.
7. SEVERABILITY. If any provision of this agreement is held to be
unenforceable, this agreement will remain in effect with the provision
omitted, unless omission would frustrate the intent of the parties, in
which case this agreement will immediately terminate.
8. RESERVATION OF RIGHTS. All rights not expressly granted in this agreement
are reserved by WireGuard LLC. For example, WireGuard LLC reserves the
right at any time to cease development of Software, to alter distribution
details, features, specifications, capabilities, functions, licensing
terms, release dates, APIs, ABIs, general availability, or other
characteristics of the Software.

336
addon/win/README.md Normal file

@ -0,0 +1,336 @@
# [WireGuard](https://www.wireguard.com/) for the NT Kernel
### High performance in-kernel WireGuard implementation for Windows
WireGuardNT is an implementation of WireGuard, for the NT Kernel as used in Windows 7, 8, 8.1, 10, and 11, supporting AMD64, x86, ARM64, and ARM processors.
#### Not the droids you're looking for
**If you've come here looking to run [WireGuard on Windows](https://git.zx2c4.com/wireguard-windows/about/), you're in the wrong place. Instead, head on over to the [WireGuard Download Page](https://www.wireguard.com/install/) to download the WireGuard application.** Alternatively, if you've come here looking to embed WireGuard into your Windows program, **you are still in the wrong place**. Instead, head on over to the [embeddable DLL service project](https://git.zx2c4.com/wireguard-windows/about/embeddable-dll-service/README.md), to get everything you need to bake WireGuard into your Windows programs. These projects use WireGuardNT inside.
## Usage
#### Download
WireGuardNT is deployed as a platform-specific `wireguard.dll` file. Install the `wireguard.dll` file side-by-side with your application. Download the dll from [the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/), alongside the header file for your application described below.
#### API
Include the [`wireguard.h` file](https://git.zx2c4.com/wireguard-nt/tree/api/wireguard.h) in your project simply by copying it there and dynamically load the `wireguard.dll` using [`LoadLibraryEx()`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa) and [`GetProcAddress()`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress) to resolve each function, using the typedefs provided in the header file. The [`InitializeWireGuardNT` function in the example.c code](https://git.zx2c4.com/wireguard-nt/tree/example/example.c) provides this in a function that you can simply copy and paste.
With the library setup, WireGuardNT can then be used by first creating an adapter, configuring it, and then setting its status to "up". Adapters have names (e.g. "OfficeNet") and types (e.g. "WireGuard").
```C
WIREGUARD_ADAPTER_HANDLE Adapter1 = WireGuardCreateAdapter(L"OfficeNet", L"WireGuard", &SomeFixedGUID1);
WIREGUARD_ADAPTER_HANDLE Adapter2 = WireGuardCreateAdapter(L"HomeNet", L"WireGuard", &SomeFixedGUID2);
WIREGUARD_ADAPTER_HANDLE Adapter3 = WireGuardCreateAdapter(L"Data Center", L"WireGuard", &SomeFixedGUID3);
```
After creating an adapter, we can use it by setting a configuration and setting its status to "up":
```C
struct
{
WIREGUARD_INTERFACE Interface;
WIREGUARD_PEER FirstPeer;
WIREGUARD_ALLOWED_IP FirstPeerAllowedIP1;
WIREGUARD_ALLOWED_IP FirstPeerAllowedIP2;
WIREGUARD_PEER SecondPeer;
WIREGUARD_ALLOWED_IP SecondtPeerAllowedIP1;
} Config = {
.Interface = {
.Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY,
.PrivateKey = ...,
.PeersCount = 2
},
.FirstPeer = {
.Flags = WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_ENDPOINT,
.PublicKey = ...,
.Endpoint = ...,
.AllowedIPsCount = 2
},
.FirstPeerAllowedIP1 = { ... },
...
};
WireGuardSetConfiguration(Adapter1, &Config.Interface, sizeof(Config));
WireGuardSetAdapterState(Adapter1, WIREGUARD_ADAPTER_STATE_UP);
```
You are *highly encouraged* to read the [**example.c short example**](https://git.zx2c4.com/wireguard-nt/tree/example/example.c) to see how to put together a simple network tunnel. The example one connects to the [demo server](https://demo.wireguard.com/).
The various functions and definitions are [documented in `wireguard.h`](https://git.zx2c4.com/wireguard-nt/tree/api/wireguard.h) as well as in the reference below.
## API Reference
### Type: `WIREGUARD_ADAPTER_HANDLE` - opaque type to an instance of a WireGuard adapter.
### Function: `WireGuardCreateAdapter` - creates a new adapter.
```c
WIREGUARD_ADAPTER_HANDLE WireGuardCreateAdapter(LPCWSTR Name, LPCWSTR TunnelType, const GUID *RequestedGUID);
```
Typedef'd as `WIREGUARD_CREATE_ADAPTER_FUNC`. Returns a `WIREGUARD_ADAPTER_HANDLE` if successful, which must be released with `WireGuardCloseAdapter`; otherwise returns `NULL` and sets LastError.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`LPCWSTR`|Name|The requested name of the adapter. Zero-terminated string of up to `MAX_ADAPTER_NAME-1` characters.|
|`LPCWSTR`|TunnelType|Name of the adapter tunnel type. Zero-terminated string of up to `MAX_ADAPTER_NAME-1` characters.|
|`GUID *`|RequestedGUID|The GUID of the created network adapter, which then influences NLA generation deterministically. If it is set to `NULL`, the GUID is chosen by the system at random, and hence a new NLA entry is created for each new adapter.|
### Function: `WireGuardOpenAdapter` - opens an existing adapter.
```c
WIREGUARD_ADAPTER_HANDLE WireGuardOpenAdapter(LPCWSTR Name);
```
Typedef'd as `WIREGUARD_OPEN_ADAPTER_FUNC`. Returns a `WIREGUARD_ADAPTER_HANDLE` if successful, which must be released with `WireGuardCloseAdapter`; otherwise returns `NULL` and sets LastError.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`LPCWSTR`|Name|The requested name of the adapter. Zero-terminated string of up to `MAX_ADAPTER_NAME-1` characters.|
### Function: `WireGuardCloseAdapter` - closes an open adapter and releases its resources.
```c
VOID WireGuardCloseAdapter(WIREGUARD_ADAPTER_HANDLE Adapter);
```
Typedef'd as `WIREGUARD_CLOSE_ADAPTER_FUNC`. Releases WireGuard adapter resources and, if adapter was created with `WireGuardCreateAdapter`, removes adapter.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.|
### Function: `WireGuardGetAdapterLUID` - gets the LUID of an adapter.
```c
VOID WireGuardGetAdapterLUID(WIREGUARD_ADAPTER_HANDLE Adapter, NET_LUID *Luid);
```
Typedef'd as `WIREGUARD_GET_ADAPTER_LUID_FUNC`. Returns the LUID of the adapter into the variable passed as the `Luid` argument.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.|
|`NET_LUID *` (out)|Luid|Pointer to receive adapter LUID.|
### Function: `WireGuardGetRunningDriverVersion` - gets the version of the loaded driver.
```c
DWORD WireGuardGetRunningDriverVersion(VOID);
```
Typedef'd as `WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC`. Returns the version of the WireGuardNT driver currently loaded, or zero on error and sets LastError, which is `ERROR_FILE_NOT_FOUND` if WireGuardNT is not currently loaded.
### Function: `WireGuardDeleteDriver` - deletes driver if not in use.
```c
BOOL WireGuardDeleteDriver(VOID);
```
Typedef'd as `WIREGUARD_DELETE_DRIVER_FUNC`. Deletes the WireGuardNT driver if there are no more adapters in use, and returns `TRUE` if successful, or returns `FALSE` if not and sets LastError.
### Enumeration: `WIREGUARD_LOGGER_LEVEL` - determines level of logging.
|Name|Description|
|--|--|
|`WIREGUARD_LOG_INFO`|Informational|
|`WIREGUARD_LOG_WARN`|Warning|
|`WIREGUARD_LOG_ERR`|Error|
### Callback type: `WIREGUARD_LOGGER_CALLBACK` - called for each log message.
```c
VOID WireGuardLoggerCallback(WIREGUARD_LOGGER_LEVEL Level, DWORD64 Timestamp, LPCWSTR Message);
```
Typedef'd as `WIREGUARD_LOGGER_CALLBACK`. Called by the library on each log message.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_LOGGER_LEVEL`|Level|Message level.|
|`DWORD64`|Timestamp|Message timestamp in in 100ns intervals since 1601-01-01 UTC.|
|`LPCWSTR`|Message|Message text.|
### Function: `WireGuardSetLogger` - registers logger callback function.
```c
VOID WireGuardSetLogger(WIREGUARD_LOGGER_CALLBACK NewLogger);
```
Typedef'd as `WIREGUAR_SET_LOGGER_FUNC`. After registration, the callback may be called concurrently by multiple threads. It is up to the supplied callback function, `NewLogger`, to handle synchronization. If `NewLogger` is `NULL`, logging is disabled.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_LOGGER_CALLBACK`|NewLogger|Pointer to callback function to use as a new global logger.|
### Enumeration: `WIREGUARD_ADAPTER_LOG_STATE` - determines adapter log generation.
|Name|Description|
|--|--|
|`WIREGUARD_ADAPTER_LOG_OFF`|No logs are generated from the driver.|
|`WIREGUARD_ADAPTER_LOG_ON`|Logs are generated from the driver.|
|`WIREGUARD_ADAPTER_LOG_ON_WITH_PREFIX`|Logs are generated from the driver, adapter index-prefixed.|
### Function: `WireGuardSetAdapterLogging` - sets whether adapter logs are generated.
```c
BOOL WireGuardSetAdapterLogging(WIREGUARD_ADAPTER_HANDLE Adapter, WIREGUARD_ADAPTER_LOG_STATE LogState);
```
Typedef'd as `WIREGUARD_SET_ADAPTER_LOGGING`. Sets whether and how the specified adapter logs to the logger previously set by `WireGuardSetLogger`. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.|
|`WIREGUARD_ADAPTER_LOG_STATE`|LogState|Adapter logging state.|
### Enumeration: `WIREGUARD_ADAPTER_STATE` - determines adapter state.
|Name|Description|
|--|--|
|`WIREGUARD_ADAPTER_STATE_DOWN`|Down|
|`WIREGUARD_ADAPTER_STATE_UP`|Up|
### Function: `WireGuardSetAdapterState` - sets state of adapter.
```c
BOOL WireGuardSetAdapterState(WIREGUARD_ADAPTER_HANDLE Adapter, WIREGUARD_ADAPTER_STATE State);
```
Typedef'd as `WIREGUARD_SET_ADAPTER_STATE`. Sets the specified adapter up or down. Note that sockets used by the specified adapter are owned by the process that sets the adapter up. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.|
|`WIREGUARD_ADAPTER_STATE`|State|Adapter state.|
### Function: `WireGuardGetAdapterState` - gets state of adapter.
```c
BOOL WireGuardGetAdapterState(WIREGUARD_ADAPTER_HANDLE Adapter, WIREGUARD_ADAPTER_STATE *State);
```
Typedef'd as `WIREGUARD_GET_ADAPTER_STATE`. Gets whether the specified adapter is up or down. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.|
|`WIREGUARD_ADAPTER_STATE` (out)|State|Pointer to adapter state.|
### Structure: `WIREGUARD_INTERFACE` - an interface.
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_INTERFACE_FLAG`|Flags|Bitwise combination of flags.|
|`WORD`|ListenPort|Port for UDP listen socket, or 0 to choose randomly.|
|`BYTE[WIREGUARD_KEY_LENGTH]`|PrivateKey|Private key of interface.|
|`BYTE[WIREGUARD_KEY_LENGTH]`|PublicKey|Corresponding public key of private key (unused on set).|
|`DWORD`|PeersCount|Number of peer structures following this structure.|
### Structure: `WIREGUARD_PEER` - a peer.
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_PEER_FLAG`|Flags|Bitwise combination of flags.|
|`DWORD`|Reserved|Reserved; must be zero.|
|`BYTE[WIREGUARD_KEY_LENGTH]`|PublicKey|Public key, the peer's primary identifier.|
|`BYTE[WIREGUARD_KEY_LENGTH]`|PresharedKey|Preshared key for additional layer of post-quantum resistance.|
|`WORD`|PersistentKeepalive|Persistent keep-alive seconds interval, or 0 to disable.|
|`SOCKADDR_INET`|Endpoint|Endpoint, with IP address and UDP port number.|
|`DWORD64`|TxBytes|Number of bytes transmitted (unused on set).|
|`DWORD64`|RxBytes|Number of bytes received (unused on set).|
|`DWORD64`|LastHandshake|Time of the last handshake, in 100ns intervals since 1601-01-01 UTC (unused on set).|
|`DWORD`|AllowedIPsCount|Number of allowed IP structures following this structure.|
### Structure: `WIREGUARD_ALLOWED_IP` - an IP network range.
|Type|Name|Description|
|--|--|--|
|Union|Address|IP address; the `V4` member is a `IN_ADDR` and the `V6` member is a `IN6_ADDR`.|
|`ADDRESS_FAMILY`|AddressFamily|Address family, either `AF_INET` or `AF_INET6`.|
|`BYTE`|Cidr|The CIDR of the address range.|
### Constant: `WIREGUARD_KEY_LENGTH` - the length of a key.
All WireGuard keys -- public, private, or pre-shared -- are 32 bytes in length.
### Enumeration: `WIREGUARD_INTERFACE_FLAG` - bitwise flags for interfaces.
These values may be or'd together.
|Name|Description|
|--|--|
|`WIREGUARD_INTERFACE_HAS_PUBLIC_KEY`|The PublicKey field is set (unused on set).|
|`WIREGUARD_INTERFACE_HAS_PRIVATE_KEY`|The PrivateKey field is set.|
|`WIREGUARD_INTERFACE_HAS_LISTEN_PORT`|The ListenPort field is set.|
|`WIREGUARD_INTERFACE_REPLACE_PEERS`|Remove all peers before adding new ones (unused on get).|
### Enumeration: `WIREGUARD_PEER_FLAG` - bitwise flags for peers.
These values may be or'd together.
|Name|Description|
|--|--|
|`WIREGUARD_PEER_HAS_PUBLIC_KEY`|The PublicKey field is set.|
|`WIREGUARD_PEER_HAS_PRESHARED_KEY`|The PresharedKey field is set.|
|`WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE`|The PersistentKeepAlive field is set.|
|`WIREGUARD_PEER_HAS_ENDPOINT`|The Endpoint field is set.|
|`WIREGUARD_PEER_REPLACE_ALLOWED_IPS`|Remove all allowed IPs before adding new ones (unused on get).|
|`WIREGUARD_PEER_REMOVE`|Remove specified peer (unused on get).|
|`WIREGUARD_PEER_UPDATE`|Do not add a new peer (unused on get).|
### Function: `WireGuardSetConfiguration` - sets configuration of adapter.
```c
BOOL WireGuardSetConfiguration(WIREGUARD_ADAPTER_HANDLE Adapter, const WIREGUARD_INTERFACE *Config, DWORD Bytes);
```
Typedef'd as `WIREGUARD_SET_CONFIGURATION`. Sets the configuration of the specified adapter. The `Config` argument represents a `WIREGUARD_INTERFACE` structure, immediately followed in memory by zero or more `WIREGUARD_PEER` or `WIREGUARD_ALLOWED_IP` structures. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.|
|`WIREGUARD_INTERFACE *`|Config|Adapter configuration.|
|`DWORD`|Bytes|Number of bytes of `Config` allocation.|
### Function: `WireGuardGetConfiguration` - gets configuration of adapter.
```c
BOOL WireGuardGetConfiguration(WIREGUARD_ADAPTER_HANDLE Adapter, WIREGUARD_INTERFACE *Config, DWORD *Bytes);
```
Typedef'd as `WIREGUARD_GET_CONFIGURATION`. Gets the configuration of the specified adapter. The `Config` argument represents a `WIREGUARD_INTERFACE` structure, immediately followed in memory by zero or more `WIREGUARD_PEER` or `WIREGUARD_ALLOWED_IP` structures. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError. If LastError is `ERROR_MORE_DATA`, `Bytes` is updated with the number of bytes needed for successful operation. Since that byte value can change, this function should be called in a tight loop until success or until the error is not `ERROR_MORE_DATA`.
#### Parameters
|Type|Name|Description|
|--|--|--|
|`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.|
|`WIREGUARD_INTERFACE *` (out)|Config|Adapter configuration.|
|`DWORD *` (in/out)|Bytes|Pointer to number of bytes of `Config` allocation, on input, and is updated when the function returns to the amount of bytes required.|
## Building
**Do not distribute drivers or files named "WireGuard" or "wireguard" or similar, as they will most certainly clash with official deployments. Instead distribute [`wireguard.dll` as downloaded from the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/).**
General requirements:
- [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) with Windows SDK
- [Windows Driver Kit](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk)
`wireguard-nt.sln` may be opened in Visual Studio for development and building. Be sure to run `bcdedit /set testsigning on` and then reboot before to enable unsigned driver loading. The default run sequence (F5) in Visual Studio will build the example project and its dependencies.
## License
The entire contents of [this repository](https://git.zx2c4.com/wireguard-nt/), including all documentation and example code, is "Copyright © 2018-2021 WireGuard LLC. All Rights Reserved." Source code is licensed under the [GPLv2](COPYING). Prebuilt binaries from [the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/) are released under a more permissive license suitable for more forms of software contained inside of the .zip files distributed there.

Binary file not shown.

BIN
addon/win/arm/wireguard.dll Normal file

Binary file not shown.

Binary file not shown.

@ -1,15 +1,492 @@
#include "wginterface.hh" #include "wginterface.hh"
#include "genKey/wgkeys.hh" #include "genKey/wgkeys.hh"
#include <win/wireguard.h>
#include <string>
#include <locale>
#include <codecvt>
#include <vector>
#include <map>
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
#include <accctrl.h>
#include <aclapi.h>
#include <stdio.h>
#include <stdbool.h>
#include <fcntl.h>
#include <winsock2.h>
#include <ws2ipdef.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <bcrypt.h>
#include <wincrypt.h>
#include <sysinfoapi.h>
#include <winternl.h>
#include <cstdlib>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <devguid.h>
#include <ws2def.h>
#include <netioapi.h>
#include <chrono>
#include <thread>
#include <comdef.h>
#include <Wbemidl.h>
#include <stdexcept>
const DEVPROPKEY devpkey_name = { { 0x65726957, 0x7547, 0x7261, { 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79 } }, DEVPROPID_FIRST_USABLE + 1 };
#define IFNAMSIZ MAX_ADAPTER_NAME - 1
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
static WIREGUARD_GET_ADAPTER_LUID_FUNC *WireGuardGetAdapterLUID;
static WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC *WireGuardGetRunningDriverVersion;
static WIREGUARD_DELETE_DRIVER_FUNC *WireGuardDeleteDriver;
static WIREGUARD_SET_LOGGER_FUNC *WireGuardSetLogger;
static WIREGUARD_SET_ADAPTER_LOGGING_FUNC *WireGuardSetAdapterLogging;
static WIREGUARD_GET_ADAPTER_STATE_FUNC *WireGuardGetAdapterState;
static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
// Function to check if the current user has administrator privileges
bool IsRunAsAdmin() {
BOOL fRet = FALSE;
HANDLE hToken = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
TOKEN_ELEVATION Elevation;
DWORD cbSize = sizeof(TOKEN_ELEVATION);
if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) {
fRet = Elevation.TokenIsElevated;
}
}
if (hToken) CloseHandle(hToken);
return !!fRet;
}
std::string convertWcharString(const wchar_t *wideStr) {
// Create a wstring from the wide character string
std::wstring wideString(wideStr);
// Use std::wstring_convert for conversion
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
std::string narrowString = converter.to_bytes(wideString);
// Now narrowString is a std::string containing the converted string
return narrowString;
}
LPCWSTR toLpcwstr(std::string s) {
wchar_t* wString = new wchar_t[s.length()+1];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, wString, s.length()+1);
return wString;
}
std::string parseEndpoint(SOCKADDR_INET *input) {
if (!(input->si_family == AF_INET || input->si_family == AF_INET6)) return "";
char saddr[INET6_ADDRSTRLEN];
input->si_family == AF_INET ? inet_ntop(AF_INET, &input->Ipv4.sin_addr, saddr, INET_ADDRSTRLEN) : inet_ntop(AF_INET6, &input->Ipv6.sin6_addr, saddr, INET6_ADDRSTRLEN);
if (input->si_family == AF_INET6) return std::string("[").append(saddr).append("]:").append(std::to_string(htons(input->Ipv6.sin6_port)));
return std::string(saddr).append(":").append(std::to_string(htons(input->Ipv4.sin_port)));
}
int parse_dns_retries() {
unsigned long ret;
char *retries = getenv("WG_ENDPOINT_RESOLUTION_RETRIES"), *end;
if (!retries) return 15;
if (!strcmp(retries, "infinity")) return -1;
ret = strtoul(retries, &end, 10);
if (*end || ret > INT_MAX) {
fprintf(stderr, "Unable to parse WG_ENDPOINT_RESOLUTION_RETRIES: `%s'\n", retries);
exit(1);
}
return (int)ret;
}
void insertEndpoint(SOCKADDR_INET *endpoint, std::string value) {
int ret, retries = parse_dns_retries();
char *begin, *end;
auto mmutable = strdup(value.c_str());
if (!mmutable) throw std::string("strdup");
if (!value.size()) {
free(mmutable);
throw std::string("Unable to parse empty endpoint");
}
if (mmutable[0] == '[') {
begin = &mmutable[1];
end = strchr(mmutable, ']');
if (!end) {
free(mmutable);
throw std::string("Unable to find matching brace of endpoint: ").append(value);
}
*end++ = '\0';
if (*end++ != ':' || !*end) {
free(mmutable);
throw std::string("Unable to find port of endpoint: ").append(value);
}
} else {
begin = mmutable;
end = strrchr(mmutable, ':');
if (!end || !*(end + 1)) {
free(mmutable);
throw std::string("Unable to find port of endpoint: ").append(value);
}
*end++ = '\0';
}
ADDRINFOA *resolved;
// #define min(a, b) ((a) < (b) ? (a) : (b))
for (unsigned int timeout = 1000000;; timeout = ((20000000) < (timeout * 6 / 5) ? (20000000) : (timeout * 6 / 5))) {
// ret = getaddrinfo(begin, end, &hints, &resolved);
ret = getaddrinfo(begin, end, NULL, &resolved);
if (!ret) break;
/* The set of return codes that are "permanent failures". All other possibilities are potentially transient.
*
* This is according to https://sourceware.org/glibc/wiki/NameResolver which states:
* "From the perspective of the application that calls getaddrinfo() it perhaps
* doesn't matter that much since EAI_FAIL, EAI_NONAME and EAI_NODATA are all
* permanent failure codes and the causes are all permanent failures in the
* sense that there is no point in retrying later."
*
* So this is what we do, except FreeBSD removed EAI_NODATA some time ago, so that's conditional.
*/
if (ret == EAI_NONAME || ret == EAI_FAIL ||
#ifdef EAI_NODATA
ret == EAI_NODATA ||
#endif
(retries >= 0 && !retries--)) {
free(mmutable);
throw std::string("Error code: ").append(std::to_string(ret));
}
std::this_thread::sleep_for(std::chrono::microseconds(timeout));
}
if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(SOCKADDR_IN))) memcpy(&endpoint->Ipv4, resolved->ai_addr, resolved->ai_addrlen);
else if (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(SOCKADDR_IN6)) memcpy(&endpoint->Ipv6, resolved->ai_addr, resolved->ai_addrlen);
else {
freeaddrinfo(resolved);
throw std::string("Neither IPv4 nor IPv6 address found: ").append(value);
}
freeaddrinfo(resolved);
free(mmutable);
}
std::string getErrorString(DWORD errorMessageID) {
if (errorMessageID == 0 || errorMessageID < 0) std::string("Error code: ").append(std::to_string(errorMessageID));
LPSTR messageBuffer = nullptr;
//Ask Win32 to give us the string version of that message ID.
//The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be).
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
//Copy the error message into a std::string.
std::string message(messageBuffer, size);
//Free the Win32's string's buffer.
LocalFree(messageBuffer);
return std::string("Error code: ").append(std::to_string(errorMessageID)).append(", Message: ").append(message);
}
std::string driveLoad(std::map<std::string, std::string> load) {
if (!IsRunAsAdmin()) return "Run nodejs with administrator privilegies";
auto DLLPATH = load["WIN32DLLPATH"];
if (!(DLLPATH.length())) return "Require Wireguard DLL file path!";
LPCWSTR dllPath = toLpcwstr(DLLPATH);
HMODULE WireGuardDll = LoadLibraryExW(dllPath, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!WireGuardDll) return std::string("Failed to initialize WireGuardNT, ").append(getErrorString(GetLastError()));;
#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(WireGuardDll, #Name)) == NULL)
if (X(WireGuardCreateAdapter) || X(WireGuardOpenAdapter) || X(WireGuardCloseAdapter) || X(WireGuardGetAdapterLUID) || X(WireGuardGetRunningDriverVersion) || X(WireGuardDeleteDriver) || X(WireGuardSetLogger) || X(WireGuardSetAdapterLogging) || X(WireGuardGetAdapterState) || X(WireGuardSetAdapterState) || X(WireGuardGetConfiguration) || X(WireGuardSetConfiguration))
#undef X
{
DWORD LastError = GetLastError();
FreeLibrary(WireGuardDll);
SetLastError(LastError);
return std::string("Failed to set Functions from WireGuardNT DLL, ").append(getErrorString(GetLastError()));;
}
return "";
}
std::string getWireguardVersion() {
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"getWgVersion", L"Wireguard-tools.js", NULL);
DWORD Version = WireGuardGetRunningDriverVersion();
if (Version == 0) {
auto statusErr = GetLastError();
WireGuardCloseAdapter(Adapter);
if (statusErr == ERROR_FILE_NOT_FOUND) return "Driver not loaded";
return std::string("Cannot get version drive, ").append(getErrorString(GetLastError()));
}
WireGuardCloseAdapter(Adapter);
return std::string("WireGuardNT v").append(std::to_string((Version >> 16) & 0xff)).append(".").append(std::to_string((Version >> 0) & 0xff));
}
void WireguardDevices::getInterfaces() {
// std::vector<std::string> arrayPrefix;
// arrayPrefix.push_back("ProtectedPrefix\\Administrators\\WireGuard\\");
// arrayPrefix.push_back("WireGuard\\");
// WIN32_FIND_DATA find_data;
// HANDLE find_handle;
// for (auto &preit : arrayPrefix) {
// int ret = 0;
// find_handle = FindFirstFile("\\\\.\\pipe\\*", &find_data);
// if (find_handle == INVALID_HANDLE_VALUE) continue;
// char *iface;
// do {
// if (strncmp(preit.c_str(), find_data.cFileName, strlen(preit.c_str()))) continue;
// iface = find_data.cFileName + strlen(preit.c_str());
// this->push_back(std::string("\\\\.\\pipe\\").append(preit).append(iface));
// } while (FindNextFile(find_handle, &find_data));
// FindClose(find_handle);
// if (ret < 0) throw std::string("Erro code: ").append(std::to_string(ret));
// }
HDEVINFO dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL);
if (dev_info == INVALID_HANDLE_VALUE) throw ("Cannot get devices");
for (DWORD i = 0;; ++i) {
DWORD buf_len;
WCHAR adapter_name[MAX_ADAPTER_NAME];
SP_DEVINFO_DATA dev_info_data;
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
DEVPROPTYPE prop_type;
ULONG status, problem_code;
char *interface_name;
if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
continue;
}
if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name, &prop_type, (PBYTE)adapter_name, sizeof(adapter_name), NULL, 0) || prop_type != DEVPROP_TYPE_STRING) continue;
adapter_name[_countof(adapter_name) - 1] = L'0';
if (!adapter_name[0]) continue;
buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, NULL, 0, NULL, NULL);
if (!buf_len) continue;
interface_name = (char *)malloc(buf_len);
if (!interface_name) continue;
buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
if (!buf_len) {
free(interface_name);
continue;
}
if (CM_Get_DevNode_Status(&status, &problem_code, dev_info_data.DevInst, 0) == CR_SUCCESS && (status & (DN_DRIVER_LOADED | DN_STARTED)) == (DN_DRIVER_LOADED | DN_STARTED)) this->push_back(std::string(interface_name));
free(interface_name);
}
SetupDiDestroyDeviceInfoList(dev_info);
}
void WireguardDevices::getInterfaces() {}
void WireguardDevices::deleteInterface(std::string wgName) { void WireguardDevices::deleteInterface(std::string wgName) {
throw std::string("Use userspace module"); WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(wgName));
if (!Adapter) throw std::string("This interface not exists in Wireguard-Tools.js addon!");
if (!(WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_DOWN))) throw std::string(std::string("Failed to set down interface, ").append(getErrorString(GetLastError())));
WireGuardCloseAdapter(Adapter);
}
/**
* Change point from calloc or malloc
*
* T: to
* C: From
*/
template <typename T, typename C> C* changePoint(T *x) {
// reinterpret_cast<WIREGUARD_ALLOWED_IP*>(((char*)x) + sizeof(WIREGUARD_PEER));
// std::cout << "Sizeof: " << sizeof(C) << ", " << typeid(T).name() << " -> " << typeid(C).name() << std::endl;
return reinterpret_cast<C*>(((char*)x) + sizeof(T));
} }
void WireguardConfig::getWireguardConfig() { void WireguardConfig::getWireguardConfig() {
throw std::string("Use userspace module"); WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(this->name));
if (!Adapter) throw ("This interface not exists in Wireguard-Tools.js addon!");
NET_LUID InterfaceLuid;
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
this->interfaceAddress.GetInInterface(this->name);
DWORD buf_len = 0;
WIREGUARD_INTERFACE *wg_iface = nullptr;
while (!(WireGuardGetConfiguration(Adapter, wg_iface, &buf_len))) {
free(wg_iface);
if (GetLastError() != ERROR_MORE_DATA) throw ((std::string("Failed get interface config, code: ")).append(std::to_string(GetLastError())));
wg_iface = (WIREGUARD_INTERFACE *)malloc(buf_len);
if (!wg_iface) throw std::string("Failed get interface config, ").append(std::to_string(-errno));
}
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PRIVATE_KEY) privateKey = wgKeys::toString(wg_iface->PrivateKey);
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PUBLIC_KEY) publicKey = wgKeys::toString(wg_iface->PublicKey);
portListen = 0;
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_LISTEN_PORT) portListen = wg_iface->ListenPort;
WIREGUARD_PEER *wg_peer = changePoint<WIREGUARD_INTERFACE, WIREGUARD_PEER>(wg_iface);
for (DWORD i = 0; i < wg_iface->PeersCount; i++) {
auto pubKey = wgKeys::toString(wg_peer->PublicKey);
Peer peerConfig;
peerConfig.txBytes = wg_peer->TxBytes;
peerConfig.rxBytes = wg_peer->RxBytes;
if (wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PRESHARED_KEY) peerConfig.presharedKey = wgKeys::toString(wg_peer->PresharedKey);
if (wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_ENDPOINT) peerConfig.endpoint = parseEndpoint(&wg_peer->Endpoint);
if (wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE) peerConfig.keepInterval = wg_peer->PersistentKeepalive;
if (wg_peer->LastHandshake > 0) peerConfig.lastHandshake = (wg_peer->LastHandshake - 116444736000000000LL) / (100 / 1000);
WIREGUARD_ALLOWED_IP* wg_aip = changePoint<WIREGUARD_PEER, WIREGUARD_ALLOWED_IP>(wg_peer);
for (DWORD __aip = 0; __aip < wg_peer->AllowedIPsCount; __aip++) {
char saddr[INET6_ADDRSTRLEN];
if (wg_aip->AddressFamily == AF_INET) {
inet_ntop(AF_INET, &wg_aip->Address.V6, saddr, INET_ADDRSTRLEN);
peerConfig.allowedIPs.push_back(std::string(saddr).append("/").append(std::to_string(wg_aip->Cidr)));
} else if (wg_aip->AddressFamily == AF_INET6) {
inet_ntop(AF_INET6, &wg_aip->Address.V6, saddr, INET6_ADDRSTRLEN);
peerConfig.allowedIPs.push_back(std::string(saddr).append("/").append(std::to_string(wg_aip->Cidr)));
}
++wg_aip;
}
wg_peer = reinterpret_cast<WIREGUARD_PEER*>(wg_aip);
this->Peers[pubKey] = peerConfig;
}
free(wg_iface);
} }
void WireguardConfig::setWireguardConfig() { void WireguardConfig::setWireguardConfig() {
throw std::string("Use userspace module"); DWORD buf_len = sizeof(WIREGUARD_INTERFACE);
for (auto peer : this->Peers) {
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_PEER)) throw ("Buffer overflow");
buf_len += sizeof(WIREGUARD_PEER);
for (auto aip : peer.second.allowedIPs) {
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_ALLOWED_IP)) throw ("Buffer overflow");
buf_len += sizeof(WIREGUARD_ALLOWED_IP);
}
}
WIREGUARD_INTERFACE *wg_iface = reinterpret_cast<WIREGUARD_INTERFACE*>(calloc(1, buf_len));
if (!wg_iface) throw ("Cannot alloc buff");
wg_iface->PeersCount = 0;
wgKeys::stringToKey(wg_iface->PrivateKey, privateKey);
wg_iface->Flags = WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PRIVATE_KEY;
wg_iface->ListenPort = portListen;
if (portListen >= 0 && 65535 <= portListen) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_LISTEN_PORT);
if (replacePeers) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_REPLACE_PEERS);
WIREGUARD_ALLOWED_IP *wg_aip;
WIREGUARD_PEER *wg_peer = changePoint<WIREGUARD_INTERFACE, WIREGUARD_PEER>(wg_iface);
for (auto __peer : this->Peers) {
auto peerPublicKey = __peer.first; auto peerConfig = __peer.second;
wgKeys::stringToKey(wg_peer->PublicKey, peerPublicKey);
wg_peer->Flags = WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PUBLIC_KEY;
wg_peer->AllowedIPsCount = 0;
wg_iface->PeersCount++;
if (peerConfig.removeMe) {
wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_REMOVE);
wg_peer = changePoint<WIREGUARD_PEER, WIREGUARD_PEER>(wg_peer);
} else {
if (peerConfig.presharedKey.size() == B64_WG_KEY_LENGTH) {
wgKeys::stringToKey(wg_peer->PresharedKey, peerConfig.presharedKey);
wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PRESHARED_KEY);
}
wg_peer->PersistentKeepalive = peerConfig.keepInterval;
if (peerConfig.keepInterval >= 0) wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE);
if (peerConfig.endpoint.size() > 0) {
insertEndpoint(&wg_peer->Endpoint, peerConfig.endpoint.c_str());
wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_ENDPOINT);
}
wg_aip = changePoint<WIREGUARD_PEER, WIREGUARD_ALLOWED_IP>(wg_peer);
for (auto Ip : peerConfig.allowedIPs.getIpParsed()) {
wg_aip->AddressFamily = Ip.Proto == 4 ? AF_INET : AF_INET6;
wg_aip->Cidr = Ip.Mask;
if (Ip.Proto == 6 && inet_pton(AF_INET6, Ip.Address.c_str(), &wg_aip->Address.V6) == 1) wg_aip->AddressFamily = AF_INET6;
else if (Ip.Proto == 4 && inet_pton(AF_INET, Ip.Address.c_str(), &wg_aip->Address.V4) == 1) wg_aip->AddressFamily = AF_INET;
else continue;
wg_peer->AllowedIPsCount++;
wg_aip = changePoint<WIREGUARD_ALLOWED_IP, WIREGUARD_ALLOWED_IP>(wg_aip);
if (!(wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_REPLACE_ALLOWED_IPS)) wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_REPLACE_ALLOWED_IPS);
}
wg_peer = reinterpret_cast<WIREGUARD_PEER*>(((char*)wg_aip));
}
}
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(this->name));
if (!Adapter) Adapter = WireGuardCreateAdapter(toLpcwstr(this->name), L"Wireguard-tools.js", NULL);
if (!Adapter) throw std::string("Failed to create adapter, ").append(getErrorString(GetLastError()));
else if (!WireGuardSetConfiguration(Adapter, reinterpret_cast<WIREGUARD_INTERFACE*>(wg_iface), buf_len)) {
auto status = GetLastError();
WireGuardCloseAdapter(Adapter);
throw std::string("Failed to set interface config, ").append(getErrorString(status));
} else if (!WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_UP)) {
auto status = GetLastError();
WireGuardCloseAdapter(Adapter);
throw std::string("Failed to set interface up, ").append(getErrorString(status));
} else {
this->interfaceAddress.SetInInterface(this->name);
}
free(wg_iface);
}
void IpManeger::GetInInterface(std::string interfaceName) {
// Define the InterfaceLuid of the network interface you want to query
NET_IFINDEX ind;
NET_LUID InterfaceLuid;
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(interfaceName));
if (!Adapter) throw std::string("Cannot open wireguard adapter");
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
ULONG bufferSize = 0; // Initial buffer size
// Call GetAdaptersAddresses to get the required buffer size
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize) == ERROR_BUFFER_OVERFLOW) {
// Allocate memory for the buffer
PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(bufferSize));
// Call GetAdaptersAddresses again with the allocated buffer
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, addresses, &bufferSize) == NO_ERROR) {
// Iterate through the list of adapters
for (PIP_ADAPTER_ADDRESSES adapter = addresses; adapter != nullptr; adapter = adapter->Next) {
// Check if the adapter matches the specified InterfaceLuid
if (memcmp(&adapter->Luid, &InterfaceLuid, sizeof(NET_LUID)) == 0) {
// Iterate through the list of IP addresses associated with the adapter
for (PIP_ADAPTER_UNICAST_ADDRESS address = adapter->FirstUnicastAddress; address != nullptr; address = address->Next) {
// Access the IP address in the address structure
sockaddr* sa = address->Address.lpSockaddr;
char ip[INET6_ADDRSTRLEN];
if (sa->sa_family == AF_INET) {
inet_ntop(AF_INET, &reinterpret_cast<sockaddr_in*>(sa)->sin_addr, ip, sizeof(ip));
} else if (sa->sa_family == AF_INET6) {
inet_ntop(AF_INET6, &reinterpret_cast<sockaddr_in6*>(sa)->sin6_addr, ip, sizeof(ip));
} else continue;
// Print or use the IP address as needed
this->addIPMask(std::string(ip).append("/").append(std::to_string(address->Address.iSockaddrLength)));
}
}
}
}
// Free the allocated buffer
free(addresses);
}
}
void IpManeger::SetInInterface(std::string interfaceName) {
if (this->size() == 0) return;
NET_IFINDEX interfaceIndex;
NET_LUID InterfaceLuid;
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(interfaceName));
if (!Adapter) throw std::string("Cannot open wireguard adapter");
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &interfaceIndex) != NO_ERROR) throw std::string("Cannot get interface index");
} }

@ -1,12 +1,35 @@
#include "wginterface.hh" #include "wginterface.hh"
#include <vector>
#include <string>
#include <windows.h> #include <windows.h>
#include <iostream> #include <iostream>
#include <comdef.h> #include <comdef.h>
#include <Wbemidl.h> #include <Wbemidl.h>
#include <vector> #include <windows.h>
#include <ws2ipdef.h>
#include <ws2def.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <netioapi.h>
#include <iphlpapi.h>
#include <win/wireguard.h>
#pragma comment(lib, "wbemuuid.lib") #pragma comment(lib, "wbemuuid.lib")
std::string convertWcharString(const wchar_t *wcStr) {
int MAXLEN = sizeof(wcStr);
static char *tx;
wcstombs(tx, wcStr, MAXLEN+1);
tx[MAXLEN+1] = 0;
return std::string(tx);
}
LPCWSTR toLpcwstr(std::string s) {
wchar_t* wString = new wchar_t[s.length()+1];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, wString, s.length()+1);
return wString;
}
void SetIPAddress(IWbemServices* pSvc, IWbemClassObject* pclsObj, const wchar_t* propertyName, const wchar_t* ip) { void SetIPAddress(IWbemServices* pSvc, IWbemClassObject* pclsObj, const wchar_t* propertyName, const wchar_t* ip) {
VARIANT vtProp; VARIANT vtProp;
HRESULT hres = pclsObj->Get(propertyName, 0, &vtProp, 0, 0); HRESULT hres = pclsObj->Get(propertyName, 0, &vtProp, 0, 0);
@ -18,13 +41,124 @@ void SetIPAddress(IWbemServices* pSvc, IWbemClassObject* pclsObj, const wchar_t*
if (FAILED(hres)) { if (FAILED(hres)) {
std::cerr << "Failed to set " << propertyName << ". Error code: " << hres << std::endl; std::cerr << "Failed to set " << propertyName << ". Error code: " << hres << std::endl;
throw std::string("Failed to set ").append(convertWcharString(propertyName)).append(". Error code: ").append(std::to_string(hres));
} }
} }
} }
void IpManeger::SetInInterface(std::string interfaceName) { void IpManeger::GetInInterface(std::string interfaceName) {
NET_LUID InterfaceLuid;
NET_IFINDEX ind;
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
IP_ADAPTER_INFO *pAdapterInfo;
ULONG ulOutBufLen;
DWORD dwRetVal;
pAdapterInfo = (IP_ADAPTER_INFO *)malloc( sizeof(IP_ADAPTER_INFO) );
ulOutBufLen = sizeof(IP_ADAPTER_INFO);
if (GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) {
free (pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
}
if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) != ERROR_SUCCESS) throw std::string("GetAdaptersInfo call failed with ").append(std::to_string(dwRetVal));
PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
while (pAdapter) {
if (pAdapter->Index == ind) this->push_back(std::string(pAdapter->IpAddressList.IpAddress.String).append("/32"));
pAdapter = pAdapter->Next;
}
if (pAdapterInfo) free(pAdapterInfo);
} }
void IpManeger::GetInInterface(std::string interfaceName) { void IpManeger::SetInInterface(std::string interfaceName) {
throw std::string("Use userspace module"); if (this->size() == 0) return;
HRESULT hres;
// Initialize COM
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) throw std::string("Failed to initialize COM library. Error code: ").append(std::to_string(hres));
// Initialize security
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (FAILED(hres)) {
CoUninitialize();
throw std::string("Failed to initialize security. Error code: ").append(std::to_string(hres));
}
// Obtain the initial locator
IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
if (FAILED(hres)) {
CoUninitialize();
throw std::string("Failed to create IWbemLocator object. Error code: ").append(std::to_string(hres));
}
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
if (FAILED(hres)) {
pLoc->Release();
CoUninitialize();
throw std::string("Failed to connect to ROOT\\CIMV2. Error code: ").append(std::to_string(hres));
}
// Set the security levels on the proxy
hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (FAILED(hres)) {
pSvc->Release();
pLoc->Release();
CoUninitialize();
throw std::string("Failed to set proxy blanket. Error code: ").append(std::to_string(hres));
}
// Define the IP addresses and subnet mask
const wchar_t* subnetMask = L"255.255.255.0";
const wchar_t* adapterDescription = L"Your Network Adapter Description";
// Construct the query
wchar_t query[256];
NET_IFINDEX ind;
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
swprintf(query, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE InterfaceIndex = '%s'", ind);
// Execute the query to get the network adapter configuration
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t(query), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hres)) {
pSvc->Release();
pLoc->Release();
CoUninitialize();
throw std::string("Query failed. Error code: ").append(std::to_string(hres));
}
// Iterate over the query results
IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator) {
hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (uReturn == 0) break;
// Set each IP address
for (const auto &ip : this->getIpParsed()) SetIPAddress(pSvc, pclsObj, L"IPAddress", toLpcwstr(ip.Address));
// Set the subnet mask
SetIPAddress(pSvc, pclsObj, L"IPSubnet", subnetMask);
// Save changes
hres = pSvc->PutInstance(pclsObj, WBEM_FLAG_UPDATE_ONLY, NULL, NULL);
if (FAILED(hres)) throw std::string("Failed to save changes. Error code: ").append(std::to_string(hres));
pclsObj->Release();
}
// Cleanup
pSvc->Release();
pLoc->Release();
CoUninitialize();
} }

308
addon/win/wireguard.h Normal file

@ -0,0 +1,308 @@
/* SPDX-License-Identifier: GPL-2.0 OR MIT
*
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
*/
#pragma once
#include <winsock2.h>
#include <windows.h>
#include <ipexport.h>
#include <ifdef.h>
#include <ws2ipdef.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ALIGNED
# if defined(_MSC_VER)
# define ALIGNED(n) __declspec(align(n))
# elif defined(__GNUC__)
# define ALIGNED(n) __attribute__((aligned(n)))
# else
# error "Unable to define ALIGNED"
# endif
#endif
/* MinGW is missing this one, unfortunately. */
#ifndef _Post_maybenull_
# define _Post_maybenull_
#endif
#pragma warning(push)
#pragma warning(disable : 4324) /* structure was padded due to alignment specifier */
/**
* A handle representing WireGuard adapter
*/
typedef struct _WIREGUARD_ADAPTER *WIREGUARD_ADAPTER_HANDLE;
/**
* Creates a new WireGuard adapter.
*
* @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1
* characters.
*
* @param TunnelType Name of the adapter tunnel type. Zero-terminated string of up to MAX_ADAPTER_NAME-1
* characters.
*
* @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation deterministically.
* If it is set to NULL, the GUID is chosen by the system at random, and hence a new NLA entry is
* created for each new adapter. It is called "requested" GUID because the API it uses is
* completely undocumented, and so there could be minor interesting complications with its usage.
*
* @return If the function succeeds, the return value is the adapter handle. Must be released with
* WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call
* GetLastError.
*/
typedef _Must_inspect_result_
_Return_type_success_(return != NULL)
_Post_maybenull_
WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_CREATE_ADAPTER_FUNC)
(_In_z_ LPCWSTR Name, _In_z_ LPCWSTR TunnelType, _In_opt_ const GUID *RequestedGUID);
/**
* Opens an existing WireGuard adapter.
*
* @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1
* characters.
*
* @return If the function succeeds, the return value is the adapter handle. Must be released with
* WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call
* GetLastError.
*/
typedef _Must_inspect_result_
_Return_type_success_(return != NULL)
_Post_maybenull_
WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_OPEN_ADAPTER_FUNC)(_In_z_ LPCWSTR Name);
/**
* Releases WireGuard adapter resources and, if adapter was created with WireGuardCreateAdapter, removes adapter.
*
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter.
*/
typedef VOID(WINAPI WIREGUARD_CLOSE_ADAPTER_FUNC)(_In_opt_ WIREGUARD_ADAPTER_HANDLE Adapter);
/**
* Deletes the WireGuard driver if there are no more adapters in use.
*
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
typedef _Return_type_success_(return != FALSE)
BOOL(WINAPI WIREGUARD_DELETE_DRIVER_FUNC)(VOID);
/**
* Returns the LUID of the adapter.
*
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
*
* @param Luid Pointer to LUID to receive adapter LUID.
*/
typedef VOID(WINAPI WIREGUARD_GET_ADAPTER_LUID_FUNC)(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid);
/**
* Determines the version of the WireGuard driver currently loaded.
*
* @return If the function succeeds, the return value is the version number. If the function fails, the return value is
* zero. To get extended error information, call GetLastError. Possible errors include the following:
* ERROR_FILE_NOT_FOUND WireGuard not loaded
*/
typedef _Return_type_success_(return != 0)
DWORD(WINAPI WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC)(VOID);
/**
* Determines the level of logging, passed to WIREGUARD_LOGGER_CALLBACK.
*/
typedef enum
{
WIREGUARD_LOG_INFO, /**< Informational */
WIREGUARD_LOG_WARN, /**< Warning */
WIREGUARD_LOG_ERR /**< Error */
} WIREGUARD_LOGGER_LEVEL;
/**
* Called by internal logger to report diagnostic messages
*
* @param Level Message level.
*
* @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC.
*
* @param Message Message text.
*/
typedef VOID(CALLBACK *WIREGUARD_LOGGER_CALLBACK)(
_In_ WIREGUARD_LOGGER_LEVEL Level,
_In_ DWORD64 Timestamp,
_In_z_ LPCWSTR Message);
/**
* Sets logger callback function.
*
* @param NewLogger Pointer to callback function to use as a new global logger. NewLogger may be called from various
* threads concurrently. Should the logging require serialization, you must handle serialization in
* NewLogger. Set to NULL to disable.
*/
typedef VOID(WINAPI WIREGUARD_SET_LOGGER_FUNC)(_In_ WIREGUARD_LOGGER_CALLBACK NewLogger);
/**
* Whether and how logs from the driver are collected for the callback function.
*/
typedef enum
{
WIREGUARD_ADAPTER_LOG_OFF, /**< No logs are generated from the driver. */
WIREGUARD_ADAPTER_LOG_ON, /**< Logs are generated from the driver. */
WIREGUARD_ADAPTER_LOG_ON_WITH_PREFIX /**< Logs are generated from the driver, index-prefixed. */
} WIREGUARD_ADAPTER_LOG_STATE;
/**
* Sets whether and how the adapter logs to the logger previously set up with WireGuardSetLogger.
*
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
*
* @param LogState Adapter logging state.
*
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
typedef _Return_type_success_(return != FALSE)
BOOL(WINAPI WIREGUARD_SET_ADAPTER_LOGGING_FUNC)
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_LOG_STATE LogState);
/**
* Determines the state of the adapter.
*/
typedef enum
{
WIREGUARD_ADAPTER_STATE_DOWN, /**< Down */
WIREGUARD_ADAPTER_STATE_UP, /**< Up */
} WIREGUARD_ADAPTER_STATE;
/**
* Sets the adapter state of the WireGuard adapter. Note: sockets are owned by the process that sets the state to up.
*
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
*
* @param State Adapter state.
*
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
typedef _Return_type_success_(return != FALSE)
BOOL(WINAPI WIREGUARD_SET_ADAPTER_STATE_FUNC)
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_STATE State);
/**
* Gets the adapter state of the WireGuard adapter.
*
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
*
* @param State Pointer to adapter state.
*
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
typedef _Must_inspect_result_
_Return_type_success_(return != FALSE)
BOOL(WINAPI WIREGUARD_GET_ADAPTER_STATE_FUNC)
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ WIREGUARD_ADAPTER_STATE *State);
#define WIREGUARD_KEY_LENGTH 32
typedef struct _WIREGUARD_ALLOWED_IP WIREGUARD_ALLOWED_IP;
struct ALIGNED(8) _WIREGUARD_ALLOWED_IP
{
union
{
IN_ADDR V4;
IN6_ADDR V6;
} Address; /**< IP address */
ADDRESS_FAMILY AddressFamily; /**< Address family, either AF_INET or AF_INET6 */
BYTE Cidr; /**< CIDR of allowed IPs */
};
typedef enum
{
WIREGUARD_PEER_HAS_PUBLIC_KEY = 1 << 0, /**< The PublicKey field is set */
WIREGUARD_PEER_HAS_PRESHARED_KEY = 1 << 1, /**< The PresharedKey field is set */
WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2, /**< The PersistentKeepAlive field is set */
WIREGUARD_PEER_HAS_ENDPOINT = 1 << 3, /**< The Endpoint field is set */
WIREGUARD_PEER_REPLACE_ALLOWED_IPS = 1 << 5, /**< Remove all allowed IPs before adding new ones */
WIREGUARD_PEER_REMOVE = 1 << 6, /**< Remove specified peer */
WIREGUARD_PEER_UPDATE = 1 << 7 /**< Do not add a new peer */
} WIREGUARD_PEER_FLAG;
typedef struct _WIREGUARD_PEER WIREGUARD_PEER;
struct ALIGNED(8) _WIREGUARD_PEER
{
WIREGUARD_PEER_FLAG Flags; /**< Bitwise combination of flags */
DWORD Reserved; /**< Reserved; must be zero */
BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Public key, the peer's primary identifier */
BYTE PresharedKey[WIREGUARD_KEY_LENGTH]; /**< Preshared key for additional layer of post-quantum resistance */
WORD PersistentKeepalive; /**< Seconds interval, or 0 to disable */
SOCKADDR_INET Endpoint; /**< Endpoint, with IP address and UDP port number*/
DWORD64 TxBytes; /**< Number of bytes transmitted */
DWORD64 RxBytes; /**< Number of bytes received */
DWORD64 LastHandshake; /**< Time of the last handshake, in 100ns intervals since 1601-01-01 UTC */
DWORD AllowedIPsCount; /**< Number of allowed IP structs following this struct */
};
typedef enum
{
WIREGUARD_INTERFACE_HAS_PUBLIC_KEY = (1 << 0), /**< The PublicKey field is set */
WIREGUARD_INTERFACE_HAS_PRIVATE_KEY = (1 << 1), /**< The PrivateKey field is set */
WIREGUARD_INTERFACE_HAS_LISTEN_PORT = (1 << 2), /**< The ListenPort field is set */
WIREGUARD_INTERFACE_REPLACE_PEERS = (1 << 3) /**< Remove all peers before adding new ones */
} WIREGUARD_INTERFACE_FLAG;
typedef struct _WIREGUARD_INTERFACE WIREGUARD_INTERFACE;
struct ALIGNED(8) _WIREGUARD_INTERFACE
{
WIREGUARD_INTERFACE_FLAG Flags; /**< Bitwise combination of flags */
WORD ListenPort; /**< Port for UDP listen socket, or 0 to choose randomly */
BYTE PrivateKey[WIREGUARD_KEY_LENGTH]; /**< Private key of interface */
BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Corresponding public key of private key */
DWORD PeersCount; /**< Number of peer structs following this struct */
};
/**
* Sets the configuration of the WireGuard adapter.
*
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
*
* @param Config Configuration for the adapter.
*
* @param Bytes Number of bytes in Config allocation.
*
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
typedef _Return_type_success_(return != FALSE)
BOOL(WINAPI WIREGUARD_SET_CONFIGURATION_FUNC)
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_reads_bytes_(Bytes) const WIREGUARD_INTERFACE *Config, _In_ DWORD Bytes);
/**
* Gets the configuration of the WireGuard adapter.
*
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
*
* @param Config Configuration for the adapter.
*
* @param Bytes Pointer to number of bytes in Config allocation.
*
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError, which if ERROR_MORE_DATA, Bytes is updated with the
* required size.
*/
typedef _Must_inspect_result_
_Return_type_success_(return != FALSE)
BOOL(WINAPI WIREGUARD_GET_CONFIGURATION_FUNC)
(_In_ WIREGUARD_ADAPTER_HANDLE Adapter,
_Out_writes_bytes_all_(*Bytes) WIREGUARD_INTERFACE *Config,
_Inout_ DWORD *Bytes);
#pragma warning(pop)
#ifdef __cplusplus
}
#endif

BIN
addon/win/x86/wireguard.dll Normal file

Binary file not shown.

@ -28,9 +28,15 @@ target:
sources: sources:
- "!addon/dummy/wginterface.cpp" - "!addon/dummy/wginterface.cpp"
- "addon/win/wginterface.cpp" - "addon/win/wginterface.cpp"
- "addon/win/wgip.cpp"
libraries: libraries:
- wbemuuid.lib - wbemuuid.lib
- bcrypt.lib
- crypt32.lib
- iphlpapi.lib
- kernel32.lib
- ntdll.lib
- ws2_32.lib
- setupapi.lib
defines: defines:
- "_HAS_EXCEPTIONS=1" - "_HAS_EXCEPTIONS=1"
- "ONSTARTADDON" - "ONSTARTADDON"

@ -78,7 +78,9 @@ const addon = (await loadAddon(path.resolve(__dirname, "../binding.yaml"))).wgin
listDevices(): Promise<string[]>; listDevices(): Promise<string[]>;
getConfig(name: string): Promise<GetConfig>; getConfig(name: string): Promise<GetConfig>;
setConfig(config: SetConfig): Promise<void>; setConfig(config: SetConfig): Promise<void>;
}>({}); }>({
WIN32DLLPATH: path.resolve(__dirname, "../addon/win", (process.arch === "x64" && "amd64") || (process.arch === "ia32" && "x86") || process.arch, "wireguard.dll")
});
/** /**
* Wireguard interface to kernel level * Wireguard interface to kernel level