Add clang-format #4

Closed
Sirherobrine23 wants to merge 1 commits from clangFormat into main
10 changed files with 1238 additions and 639 deletions

236
.clang-format Normal file

@ -0,0 +1,236 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveShortCaseStatements:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCaseColons: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequiresClause: true
IndentWidth: 2
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: false
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
KeepEmptyLinesAtEOF: false
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
PPIndentWidth: -1
QualifierAlignment: Leave
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveParentheses: Leave
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeJsonColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParens: Never
SpacesInParensOptions:
InCStyleCasts: false
InConditionalStatements: false
InEmptyParentheses: false
Other: false
SpacesInSquareBrackets: false
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseTab: Never
VerilogBreakBetweenInstancePorts: true
WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
...

21
.github/workflows/format.yml vendored Normal file

@ -0,0 +1,21 @@
name: Test
on:
push:
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
name: Checkout
- name: Install dependencies
run: |
export DEBIAN_FRONTEND=noninteractive
sudo apt update
sudo apt install -y clang-format
- name: format C/C++ code
run: find addons/ -path addons/tools/linux -prune -o -regex '.*\.\(cpp\|hpp\|cc\|c\|h\)' -exec clang-format -style=file -i {} \;
- run: git diff --exit-code --quiet HEAD~1 -- .

@ -1,11 +1,12 @@
#include <napi.h>
#include "wgkeys.hh"
#include <napi.h>
class privateKeyWorker : public Napi::AsyncWorker {
private:
std::string pskString;
Napi::Promise::Deferred genPromise;
public:
private:
std::string pskString;
Napi::Promise::Deferred genPromise;
public:
~privateKeyWorker() {}
privateKeyWorker(const Napi::Env env) : AsyncWorker(env), genPromise{env} {}
Napi::Promise getPromise() { return genPromise.Promise(); }
@ -18,19 +19,21 @@ class privateKeyWorker : public Napi::AsyncWorker {
Napi::HandleScope scope(Env());
genPromise.Resolve(Napi::String::New(Env(), pskString));
}
void OnError(const Napi::Error& e) override {
void OnError(const Napi::Error &e) override {
Napi::HandleScope scope(Env());
genPromise.Reject(e.Value());
}
};
class publicKeyWorker : public Napi::AsyncWorker {
private:
std::string privKey, pubString;
Napi::Promise::Deferred genPromise;
public:
private:
std::string privKey, pubString;
Napi::Promise::Deferred genPromise;
public:
~publicKeyWorker() {}
publicKeyWorker(const Napi::Env env, std::string privateKey) : AsyncWorker(env), privKey(privateKey), genPromise{env} {}
publicKeyWorker(const Napi::Env env, std::string privateKey)
: AsyncWorker(env), privKey(privateKey), genPromise{env} {}
Napi::Promise getPromise() { return genPromise.Promise(); }
void Execute() override {
wg_key interfacePrivateKey, interfacePublicKey;
@ -46,17 +49,18 @@ class publicKeyWorker : public Napi::AsyncWorker {
Napi::HandleScope scope(Env());
genPromise.Resolve(Napi::String::New(Env(), pubString));
}
void OnError(const Napi::Error& e) override {
void OnError(const Napi::Error &e) override {
Napi::HandleScope scope(Env());
genPromise.Reject(e.Value());
}
};
class presharedKeyWorker : public Napi::AsyncWorker {
private:
std::string pskString;
Napi::Promise::Deferred genPromise;
public:
private:
std::string pskString;
Napi::Promise::Deferred genPromise;
public:
~presharedKeyWorker() {}
presharedKeyWorker(const Napi::Env env) : AsyncWorker(env), genPromise{env} {}
Napi::Promise getPromise() { return genPromise.Promise(); }
@ -69,20 +73,22 @@ class presharedKeyWorker : public Napi::AsyncWorker {
Napi::HandleScope scope(Env());
genPromise.Resolve(Napi::String::New(Env(), pskString));
}
void OnError(const Napi::Error& e) override {
void OnError(const Napi::Error &e) override {
Napi::HandleScope scope(Env());
genPromise.Reject(e.Value());
}
};
class genKeysWorker : public Napi::AsyncWorker {
private:
std::string privateKey, publicKey, presharedKey;
bool withPreshared = false;
Napi::Promise::Deferred genPromise;
public:
private:
std::string privateKey, publicKey, presharedKey;
bool withPreshared = false;
Napi::Promise::Deferred genPromise;
public:
~genKeysWorker() {}
genKeysWorker(const Napi::Env env, bool withPresharedKey) : AsyncWorker(env), withPreshared(withPresharedKey), genPromise{env} {}
genKeysWorker(const Napi::Env env, bool withPresharedKey)
: AsyncWorker(env), withPreshared(withPresharedKey), genPromise{env} {}
Napi::Promise getPromise() { return genPromise.Promise(); }
void Execute() override {
wg_key keyPriv, preshe, pub;
@ -93,7 +99,8 @@ class genKeysWorker : public Napi::AsyncWorker {
wgKeys::generatePublic(pub, keyPriv);
publicKey = wgKeys::toString(pub);
if (!withPreshared) return;
if (!withPreshared)
return;
wgKeys::generatePreshared(preshe);
presharedKey = wgKeys::toString(preshe);
}
@ -103,11 +110,12 @@ class genKeysWorker : public Napi::AsyncWorker {
auto keys = Napi::Object::New(env);
keys.Set("privateKey", privateKey);
keys.Set("publicKey", publicKey);
if (withPreshared) keys.Set("presharedKey", presharedKey);
if (withPreshared)
keys.Set("presharedKey", presharedKey);
genPromise.Resolve(keys);
}
void OnError(const Napi::Error& e) override {
void OnError(const Napi::Error &e) override {
Napi::HandleScope scope(Env());
genPromise.Reject(e.Value());
}
@ -119,45 +127,56 @@ Napi::Object Init(Napi::Env exportsEnv, Napi::Object exports) {
constants.Set("B64_WG_KEY_LENGTH", B64_WG_KEY_LENGTH);
exports.Set("constants", constants);
exports.Set("presharedKey", Napi::Function::New(exportsEnv, [&](const Napi::CallbackInfo& info) {
const Napi::Env env = info.Env();
exports.Set(
"presharedKey",
Napi::Function::New(exportsEnv, [&](const Napi::CallbackInfo &info) {
const Napi::Env env = info.Env();
// Callback function is latest argument
auto *Gen = new presharedKeyWorker(env);
Gen->Queue();
return Gen->getPromise();
}));
// Callback function is latest argument
auto *Gen = new presharedKeyWorker(env);
Gen->Queue();
return Gen->getPromise();
}));
exports.Set("privateKey", Napi::Function::New(exportsEnv, [&](const Napi::CallbackInfo& info) {
const Napi::Env env = info.Env();
exports.Set(
"privateKey",
Napi::Function::New(exportsEnv, [&](const Napi::CallbackInfo &info) {
const Napi::Env env = info.Env();
// Callback function is latest argument
auto *Gen = new privateKeyWorker(env);
Gen->Queue();
return Gen->getPromise();
}));
// Callback function is latest argument
auto *Gen = new privateKeyWorker(env);
Gen->Queue();
return Gen->getPromise();
}));
exports.Set("publicKey", Napi::Function::New(exportsEnv, [&](const Napi::CallbackInfo& info) -> Napi::Value {
const Napi::Env env = info.Env();
if (!(info[0].IsString())) {
Napi::Error::New(env, "Require private key").ThrowAsJavaScriptException();
return env.Undefined();
}
exports.Set(
"publicKey",
Napi::Function::New(exportsEnv,
[&](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
if (!(info[0].IsString())) {
Napi::Error::New(env, "Require private key")
.ThrowAsJavaScriptException();
return env.Undefined();
}
// Callback function is latest argument
auto *Gen = new publicKeyWorker(env, info[0].ToString().Utf8Value().c_str());
Gen->Queue();
return Gen->getPromise();
}));
// Callback function is latest argument
auto *Gen = new publicKeyWorker(
env, info[0].ToString().Utf8Value().c_str());
Gen->Queue();
return Gen->getPromise();
}));
exports.Set("genKey", Napi::Function::New(exportsEnv, [&](const Napi::CallbackInfo &info) {
const Napi::Env env = info.Env();
bool withPreshared = false;
if (info[0].IsBoolean()) withPreshared = info[0].ToBoolean().Value();
auto Gen = new genKeysWorker(env, withPreshared);
Gen->Queue();
return Gen->getPromise();
}));
exports.Set("genKey", Napi::Function::New(
exportsEnv, [&](const Napi::CallbackInfo &info) {
const Napi::Env env = info.Env();
bool withPreshared = false;
if (info[0].IsBoolean())
withPreshared = info[0].ToBoolean().Value();
auto Gen = new genKeysWorker(env, withPreshared);
Gen->Queue();
return Gen->getPromise();
}));
return exports;
}
NODE_API_MODULE(addon, Init);

@ -1,6 +1,6 @@
#include "wgkeys.hh"
#include <errno.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <iostream>
#include <random>
@ -15,20 +15,23 @@
static void encode_base64(char dest[4], const uint8_t src[3]) {
const uint8_t input[] = {
static_cast<uint8_t>((src[0] >> 2) & 63),
static_cast<uint8_t>(((src[0] << 4) | (src[1] >> 4)) & 63),
static_cast<uint8_t>(((src[1] << 2) | (src[2] >> 6)) & 63),
static_cast<uint8_t>(src[2] & 63)
};
static_cast<uint8_t>((src[0] >> 2) & 63),
static_cast<uint8_t>(((src[0] << 4) | (src[1] >> 4)) & 63),
static_cast<uint8_t>(((src[1] << 2) | (src[2] >> 6)) & 63),
static_cast<uint8_t>(src[2] & 63)};
unsigned int i;
for (i = 0; i < 4; ++i) dest[i] = input[i] + 'A' + (((25 - input[i]) >> 8) & 6) - (((51 - input[i]) >> 8) & 75) - (((61 - input[i]) >> 8) & 15) + (((62 - input[i]) >> 8) & 3);
for (i = 0; i < 4; ++i)
dest[i] = input[i] + 'A' + (((25 - input[i]) >> 8) & 6) -
(((51 - input[i]) >> 8) & 75) - (((61 - input[i]) >> 8) & 15) +
(((62 - input[i]) >> 8) & 3);
}
void keyToBase64(wg_key_b64_string base64, const wg_key key) {
unsigned int i;
for (i = 0; i < 32 / 3; ++i) encode_base64(&base64[i * 4], &key[i * 3]);
const uint8_t tempKey[3] = { key[i * 3 + 0], key[i * 3 + 1], 0 };
for (i = 0; i < 32 / 3; ++i)
encode_base64(&base64[i * 4], &key[i * 3]);
const uint8_t tempKey[3] = {key[i * 3 + 0], key[i * 3 + 1], 0};
encode_base64(&base64[i * 4], tempKey);
base64[sizeof(wg_key_b64_string) - 2] = '=';
base64[sizeof(wg_key_b64_string) - 1] = '\0';
@ -38,19 +41,28 @@ static int decodeBase64(const char src[4]) {
int val = 0;
unsigned int i;
for (i = 0; i < 4; ++i) val |= (-1 + ((((('A' - 1) - src[i]) & (src[i] - ('Z' + 1))) >> 8) & (src[i] - 64)) + ((((('a' - 1) - src[i]) & (src[i] - ('z' + 1))) >> 8) & (src[i] - 70)) + ((((('0' - 1) - src[i]) & (src[i] - ('9' + 1))) >> 8) & (src[i] + 5)) + ((((('+' - 1) - src[i]) & (src[i] - ('+' + 1))) >> 8) & 63) + ((((('/' - 1) - src[i]) & (src[i] - ('/' + 1))) >> 8) & 64)) << (18 - 6 * i);
for (i = 0; i < 4; ++i)
val |=
(-1 +
((((('A' - 1) - src[i]) & (src[i] - ('Z' + 1))) >> 8) &
(src[i] - 64)) +
((((('a' - 1) - src[i]) & (src[i] - ('z' + 1))) >> 8) &
(src[i] - 70)) +
((((('0' - 1) - src[i]) & (src[i] - ('9' + 1))) >> 8) & (src[i] + 5)) +
((((('+' - 1) - src[i]) & (src[i] - ('+' + 1))) >> 8) & 63) +
((((('/' - 1) - src[i]) & (src[i] - ('/' + 1))) >> 8) & 64))
<< (18 - 6 * i);
return val;
}
#ifdef _WIN32
static volatile void * (*memset_func)(void *, int, size_t) = (volatile void * (*)(void *, int, size_t))&memset;
void memzero_explicit(void *s, size_t count) {
memset_func(s, 0, count);
}
static volatile void *(*memset_func)(void *, int, size_t) =
(volatile void *(*)(void *, int, size_t)) & memset;
void memzero_explicit(void *s, size_t count) { memset_func(s, 0, count); }
#else
static __attribute__((noinline)) void memzero_explicit(void *s, size_t count) {
memset(s, 0, count);
__asm__ __volatile__("": :"r"(s) :"memory");
__asm__ __volatile__("" : : "r"(s) : "memory");
}
#endif
@ -109,21 +121,25 @@ static void pack(uint8_t *o, const fe n) {
static void add(fe o, const fe a, const fe b) {
int i;
for (i = 0; i < 16; ++i) o[i] = a[i] + b[i];
for (i = 0; i < 16; ++i)
o[i] = a[i] + b[i];
}
static void subtract(fe o, const fe a, const fe b) {
int i;
for (i = 0; i < 16; ++i) o[i] = a[i] - b[i];
for (i = 0; i < 16; ++i)
o[i] = a[i] - b[i];
}
static void multmod(fe o, const fe a, const fe b) {
int i, j;
int64_t t[31] = { 0 };
int64_t t[31] = {0};
for (i = 0; i < 16; ++i) {
for (j = 0; j < 16; ++j) t[i + j] += a[i] * b[j];
for (j = 0; j < 16; ++j)
t[i + j] += a[i] * b[j];
}
for (i = 0; i < 15; ++i) t[i] += 38 * t[i + 16];
for (i = 0; i < 15; ++i)
t[i] += 38 * t[i + 16];
memcpy(o, t, sizeof(fe));
carry(o);
carry(o);
@ -136,27 +152,39 @@ static void invert(fe o, const fe i) {
memcpy(c, i, sizeof(c));
for (a = 253; a >= 0; --a) {
multmod(c, c, c);
if (a != 2 && a != 4) multmod(c, c, i);
if (a != 2 && a != 4)
multmod(c, c, i);
}
memcpy(o, c, sizeof(fe));
memzero_explicit(c, sizeof(c));
}
void wgKeys::generatePreshared(wg_key preshared_key) {
#if _WIN32 || defined(__CYGWIN__)
#if _WIN32 || defined(__CYGWIN__)
HCRYPTPROV hCryptProv;
BOOL winStatus;
if ((winStatus = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))) winStatus = CryptGenRandom(hCryptProv, sizeof(wg_key), (BYTE*)preshared_key);
if ((winStatus = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)))
winStatus =
CryptGenRandom(hCryptProv, sizeof(wg_key), (BYTE *)preshared_key);
CryptReleaseContext(hCryptProv, 0);
if (winStatus) return;
if (winStatus)
return;
#elif defined(__OpenBSD__) || (defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12) || (defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)))
if (!getentropy(preshared_key, sizeof(wg_key))) return;
#elif defined(__OpenBSD__) || \
(defined(__APPLE__) && \
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12) || \
(defined(__GLIBC__) && \
(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)))
if (!getentropy(preshared_key, sizeof(wg_key)))
return;
#elif defined(__NR_getrandom) && defined(__linux__)
if (syscall(__NR_getrandom, preshared_key, sizeof(wg_key), 0) == sizeof(wg_key)) return;
#elif defined(__NR_getrandom) && defined(__linux__)
if (syscall(__NR_getrandom, preshared_key, sizeof(wg_key), 0) ==
sizeof(wg_key))
return;
#elif __linux__ || _ANDROID__ || __termux__
#elif __linux__ || _ANDROID__ || __termux__
size_t ret, i;
int fd;
fd = open("/dev/urandom", O_RDONLY);
@ -167,7 +195,7 @@ void wgKeys::generatePreshared(wg_key preshared_key) {
}
close(fd);
return;
#endif
#endif
std::random_device rd;
for (uint8_t i = 0; i < sizeof(wg_key); ++i) {
@ -191,7 +219,7 @@ void wgKeys::generatePrivate(wg_key private_key) {
void wgKeys::generatePublic(wg_key public_key, const wg_key private_key) {
int i, r;
uint8_t z[32];
fe a = { 1 }, b = { 9 }, c = { 0 }, d = { 1 }, e, f;
fe a = {1}, b = {9}, c = {0}, d = {1}, e, f;
memcpy(z, private_key, sizeof(z));
clamp_key(z);
@ -212,12 +240,12 @@ void wgKeys::generatePublic(wg_key public_key, const wg_key private_key) {
subtract(a, a, c);
multmod(b, a, a);
subtract(c, d, f);
const fe abc = { 0xdb41, 1 };
const fe abc = {0xdb41, 1};
multmod(a, c, abc);
add(a, a, d);
multmod(c, c, a);
multmod(a, d, f);
const fe abc2 = { 9 };
const fe abc2 = {9};
multmod(d, b, abc2);
multmod(b, e, e);
cswap(a, b, r);
@ -237,8 +265,7 @@ void wgKeys::generatePublic(wg_key public_key, const wg_key private_key) {
memzero_explicit(f, sizeof(f));
}
bool key_is_zero(const uint8_t key[32])
{
bool key_is_zero(const uint8_t key[32]) {
volatile uint8_t acc = 0;
for (unsigned int i = 0; i < 32; ++i) {
@ -250,7 +277,10 @@ bool key_is_zero(const uint8_t key[32])
void wgKeys::stringToKey(wg_key key, std::string keyBase64) {
auto base64 = keyBase64.c_str();
if (keyBase64.length() != B64_WG_KEY_LENGTH || base64[B64_WG_KEY_LENGTH - 1] != '=') throw std::string("invalid key, length: ").append(std::to_string(keyBase64.length()));
if (keyBase64.length() != B64_WG_KEY_LENGTH ||
base64[B64_WG_KEY_LENGTH - 1] != '=')
throw std::string("invalid key, length: ")
.append(std::to_string(keyBase64.length()));
unsigned int i;
int val;
@ -263,21 +293,25 @@ void wgKeys::stringToKey(wg_key key, std::string keyBase64) {
key[i * 3 + 1] = (val >> 8) & 0xff;
key[i * 3 + 2] = val & 0xff;
}
const char tempDecode[4] = {base64[i * 4 + 0], base64[i * 4 + 1], base64[i * 4 + 2], 'A'};
const char tempDecode[4] = {base64[i * 4 + 0], base64[i * 4 + 1],
base64[i * 4 + 2], 'A'};
val = decodeBase64(tempDecode);
ret |= ((uint32_t)val >> 31) | (val & 0xff);
key[i * 3 + 0] = (val >> 16) & 0xff;
key[i * 3 + 1] = (val >> 8) & 0xff;
int status = EINVAL & ~((ret - 1) >> 8);
if (status != 0) throw std::string("Cannot decode key, ret code: ").append(std::to_string(status));
if (status != 0)
throw std::string("Cannot decode key, ret code: ")
.append(std::to_string(status));
}
std::string wgKeys::toString(const wg_key key) {
wg_key_b64_string base64;
unsigned int i;
for (i = 0; i < 32 / 3; ++i) encode_base64(&base64[i * 4], &key[i * 3]);
const uint8_t tempKey[3] = { key[i * 3 + 0], key[i * 3 + 1], 0 };
for (i = 0; i < 32 / 3; ++i)
encode_base64(&base64[i * 4], &key[i * 3]);
const uint8_t tempKey[3] = {key[i * 3 + 0], key[i * 3 + 1], 0};
encode_base64(&base64[i * 4], tempKey);
base64[sizeof(wg_key_b64_string) - 2] = '=';
base64[sizeof(wg_key_b64_string) - 1] = '\0';

@ -1,14 +1,10 @@
#include <napi.h>
#include <wginterface.hh>
#include <net/if.h>
#include <wginterface.hh>
unsigned long maxName() {
return IFNAMSIZ;
}
unsigned long maxName() { return IFNAMSIZ; }
std::string versionDrive() {
return "Userspace";
}
std::string versionDrive() { return "Userspace"; }
void listDevices::Execute() {}
void deleteInterface::Execute() {}

@ -1,31 +1,30 @@
#include <napi.h>
#include <iostream>
#include <unistd.h>
#include <time.h>
#include "linux/set_ip.cpp"
#include "wginterface.hh"
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if_link.h>
#include <linux/if_addr.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <sys/ioctl.h>
#include <cerrno>
#include <ifaddrs.h>
#include <iostream>
#include <linux/if_addr.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_link.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <napi.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sysexits.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "wginterface.hh"
#include "linux/set_ip.cpp"
#include <sysexits.h>
#include <time.h>
#include <unistd.h>
extern "C" {
#include "linux/wireguard.h"
#include "linux/wireguard.h"
}
#define SETCONFIG 1
@ -33,19 +32,17 @@ extern "C" {
#define LISTDEV 1
#define DELIFACE 1
unsigned long maxName() {
return IFNAMSIZ;
}
unsigned long maxName() { return IFNAMSIZ; }
std::string versionDrive() {
return "Kernel";
}
std::string versionDrive() { return "Kernel"; }
void listDevices::Execute() {
char *device_name, *devicesList = wg_list_device_names();
if (!devicesList) return SetError("Unable to get device names");
if (!devicesList)
return SetError("Unable to get device names");
size_t len;
for ((device_name) = (devicesList), (len) = 0; ((len) = strlen(device_name)); (device_name) += (len) + 1) {
for ((device_name) = (devicesList), (len) = 0; ((len) = strlen(device_name));
(device_name) += (len) + 1) {
listInfo setInfo;
setInfo.tunType = "kernel";
deviceNames[std::string(device_name)] = setInfo;
@ -58,7 +55,8 @@ int setInterface(std::string wgName) {
char *device_name, *devicesList = wg_list_device_names();
if (!!devicesList) {
auto createInterface = true;
for ((device_name) = (devicesList), (len) = 0; ((len) = strlen(device_name)); (device_name) += (len) + 1) {
for ((device_name) = (devicesList), (len) = 0;
((len) = strlen(device_name)); (device_name) += (len) + 1) {
if (device_name == wgName.c_str()) {
createInterface = false;
break;
@ -66,7 +64,8 @@ int setInterface(std::string wgName) {
}
free(devicesList);
len = 0;
if (createInterface) len = wg_add_device(wgName.c_str());
if (createInterface)
len = wg_add_device(wgName.c_str());
}
return len;
@ -76,13 +75,17 @@ void deleteInterface::Execute() {
size_t len = 0;
char *device_name, *devicesList = wg_list_device_names();
if (!!devicesList) {
for ((device_name) = (devicesList), (len) = 0; ((len) = strlen(device_name)); (device_name) += (len) + 1) {
for ((device_name) = (devicesList), (len) = 0;
((len) = strlen(device_name)); (device_name) += (len) + 1) {
if (device_name == wgName.c_str()) {
if ((len = wg_add_device(wgName.c_str())) < 0) {
std::string err = "Error code: ";
err = err.append(std::to_string(len));
if (len == -ENOMEM) err = "Out of memory";
else if (len == -errno) err = ((std::string)"Cannot add device, code: ").append(std::to_string(len));
if (len == -ENOMEM)
err = "Out of memory";
else if (len == -errno)
err = ((std::string) "Cannot add device, code: ")
.append(std::to_string(len));
SetError(err);
}
break;
@ -97,8 +100,11 @@ void setConfig::Execute() {
if (res < 0) {
std::string err = "Error code: ";
err = err.append(std::to_string(res));
if (res == -ENOMEM) err = "Out of memory";
else if (res == -errno) err = ((std::string)"Cannot add device, code: ").append(std::to_string(res));
if (res == -ENOMEM)
err = "Out of memory";
else if (res == -errno)
err = ((std::string) "Cannot add device, code: ")
.append(std::to_string(res));
SetError(err);
return;
}
@ -120,17 +126,21 @@ void setConfig::Execute() {
// Port listenings
if (portListen > 0 && 25565 < portListen) {
deviceStruct->listen_port = portListen;
deviceStruct->flags = (wg_device_flags)(deviceStruct->flags|WGDEVICE_HAS_LISTEN_PORT);
deviceStruct->flags =
(wg_device_flags)(deviceStruct->flags | WGDEVICE_HAS_LISTEN_PORT);
}
// Linux firewall mark
if (fwmark >= 0) {
deviceStruct->fwmark = fwmark;
deviceStruct->flags = (wg_device_flags)(deviceStruct->flags|WGDEVICE_HAS_FWMARK);
deviceStruct->flags =
(wg_device_flags)(deviceStruct->flags | WGDEVICE_HAS_FWMARK);
}
// Replace Peers
if (replacePeers) deviceStruct->flags = (wg_device_flags)(deviceStruct->flags|WGDEVICE_REPLACE_PEERS);
if (replacePeers)
deviceStruct->flags =
(wg_device_flags)(deviceStruct->flags | WGDEVICE_REPLACE_PEERS);
unsigned int peerIndex = 0;
for (auto it = peersVector.begin(); it != peersVector.end(); ++it) {
@ -144,18 +154,23 @@ void setConfig::Execute() {
peerStruct->flags = (wg_peer_flags)WGPEER_HAS_PUBLIC_KEY;
// Remove Peer
if (peerConfig.removeMe) peerStruct->flags = (wg_peer_flags)(peerStruct->flags|WGPEER_REMOVE_ME);
if (peerConfig.removeMe)
peerStruct->flags = (wg_peer_flags)(peerStruct->flags | WGPEER_REMOVE_ME);
else {
// Set preshared key if present
if (peerConfig.presharedKey.length() > 0) {
wg_key_from_base64(peerStruct->preshared_key, peerConfig.presharedKey.c_str());
peerStruct->flags = (wg_peer_flags)(peerStruct->flags|WGPEER_HAS_PRESHARED_KEY);
wg_key_from_base64(peerStruct->preshared_key,
peerConfig.presharedKey.c_str());
peerStruct->flags =
(wg_peer_flags)(peerStruct->flags | WGPEER_HAS_PRESHARED_KEY);
}
// Set Keepalive
if (peerConfig.keepInterval > 0) {
peerStruct->persistent_keepalive_interval = peerConfig.keepInterval;
peerStruct->flags = (wg_peer_flags)(peerStruct->flags|WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL);
peerStruct->flags =
(wg_peer_flags)(peerStruct->flags |
WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL);
}
// Set endpoint
@ -190,37 +205,51 @@ void setConfig::Execute() {
}
addrinfo *resolved;
addrinfo hints = {
ai_family: AF_UNSPEC,
ai_socktype: SOCK_DGRAM,
ai_protocol: IPPROTO_UDP
ai_family : AF_UNSPEC,
ai_socktype : SOCK_DGRAM,
ai_protocol : IPPROTO_UDP
};
#define min(a, b) ((a) < (b) ? (a) : (b))
for (unsigned int timeout = 1000000;; timeout = min(20000000, timeout * 6 / 5)) {
#define min(a, b) ((a) < (b) ? (a) : (b))
for (unsigned int timeout = 1000000;;
timeout = min(20000000, timeout * 6 / 5)) {
ret = getaddrinfo(begin, end, &hints, &resolved);
if (!ret) break;
if (!ret)
break;
if (ret == EAI_NONAME || ret == EAI_FAIL ||
#ifdef EAI_NODATA
#ifdef EAI_NODATA
ret == EAI_NODATA ||
#endif
#endif
(retries >= 0 && !retries--)) {
free(Endpoint);
fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), peerConfig.endpoint.c_str());
fprintf(stderr, "%s: `%s'\n",
ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret),
peerConfig.endpoint.c_str());
SetError("Unable to resolve endpoint");
return;
}
fprintf(stderr, "%s: `%s'. Trying again in %.2f seconds...\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), peerConfig.endpoint.c_str(), timeout / 1000000.0);
fprintf(stderr, "%s: `%s'. Trying again in %.2f seconds...\n",
ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret),
peerConfig.endpoint.c_str(), timeout / 1000000.0);
usleep(timeout);
}
if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(sockaddr_in)) || (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(sockaddr_in6))) {
if ((resolved->ai_family == AF_INET &&
resolved->ai_addrlen == sizeof(sockaddr_in)) ||
(resolved->ai_family == AF_INET6 &&
resolved->ai_addrlen == sizeof(sockaddr_in6))) {
memcpy(&endpoint, resolved->ai_addr, resolved->ai_addrlen);
memccpy(&peerStruct->endpoint.addr, &endpoint, 0, sizeof(peerStruct->endpoint.addr));
memccpy(&peerStruct->endpoint.addr, &endpoint, 0,
sizeof(peerStruct->endpoint.addr));
if (resolved->ai_family == AF_INET) {
peerStruct->endpoint.addr4.sin_addr.s_addr = ((sockaddr_in *)&endpoint)->sin_addr.s_addr;
peerStruct->endpoint.addr4.sin_port = ((sockaddr_in *)&endpoint)->sin_port;
peerStruct->endpoint.addr4.sin_addr.s_addr =
((sockaddr_in *)&endpoint)->sin_addr.s_addr;
peerStruct->endpoint.addr4.sin_port =
((sockaddr_in *)&endpoint)->sin_port;
peerStruct->endpoint.addr4.sin_family = AF_INET;
} else {
peerStruct->endpoint.addr6.sin6_addr = ((struct sockaddr_in6 *)&endpoint)->sin6_addr;
peerStruct->endpoint.addr6.sin6_port = ((struct sockaddr_in6 *)&endpoint)->sin6_port;
peerStruct->endpoint.addr6.sin6_addr =
((struct sockaddr_in6 *)&endpoint)->sin6_addr;
peerStruct->endpoint.addr6.sin6_port =
((struct sockaddr_in6 *)&endpoint)->sin6_port;
peerStruct->endpoint.addr6.sin6_family = AF_INET6;
}
} else {
@ -235,36 +264,43 @@ void setConfig::Execute() {
// Set allowed IPs
if (peerConfig.allowedIPs.size() > 0) {
peerStruct->flags = (wg_peer_flags)(peerStruct->flags|WGPEER_REPLACE_ALLOWEDIPS);
for (unsigned int allowIndex = 0; allowIndex < peerConfig.allowedIPs.size(); allowIndex++) {
peerStruct->flags =
(wg_peer_flags)(peerStruct->flags | WGPEER_REPLACE_ALLOWEDIPS);
for (unsigned int allowIndex = 0;
allowIndex < peerConfig.allowedIPs.size(); allowIndex++) {
auto ip = peerConfig.allowedIPs[allowIndex];
unsigned long cidr = 0;
if (ip.find("/") != std::string::npos) {
cidr = std::stoi(ip.substr(ip.find("/")+1));
cidr = std::stoi(ip.substr(ip.find("/") + 1));
ip = ip.substr(0, ip.find("/"));
}
wg_allowedip *newAllowedIP = new wg_allowedip({family: AF_UNSPEC});
wg_allowedip *newAllowedIP = new wg_allowedip({family : AF_UNSPEC});
if (strchr(ip.c_str(), ':')) {
if (inet_pton(AF_INET6, ip.c_str(), &newAllowedIP->ip6) == 1) {
newAllowedIP->family = AF_INET6;
if (cidr == 0) cidr = 128;
if (cidr == 0)
cidr = 128;
}
} else {
if (inet_pton(AF_INET, ip.c_str(), &newAllowedIP->ip4) == 1) {
newAllowedIP->family = AF_INET;
if (cidr == 0) cidr = 32;
if (cidr == 0)
cidr = 32;
}
}
if (newAllowedIP->family == AF_UNSPEC || cidr <= 0) continue;
if (newAllowedIP->family == AF_UNSPEC || cidr <= 0)
continue;
newAllowedIP->cidr = cidr;
if (allowIndex > 0) newAllowedIP->next_allowedip = peerStruct->first_allowedip;
if (allowIndex > 0)
newAllowedIP->next_allowedip = peerStruct->first_allowedip;
peerStruct->first_allowedip = newAllowedIP;
}
}
}
// Add to Peer struct
if (peerIndex > 0) peerStruct->next_peer = deviceStruct->first_peer;
if (peerIndex > 0)
peerStruct->next_peer = deviceStruct->first_peer;
deviceStruct->first_peer = peerStruct;
}
@ -272,34 +308,47 @@ void setConfig::Execute() {
if ((res = wg_set_device(deviceStruct)) < 0) {
std::string err = "Set wireguard config Error code: ";
err = err.append(std::to_string(res));
if (res == -ENODEV) err = "No such device";
else if (res == -EINVAL) err = "Invalid argument";
else if (res == -ENOSPC) err = "No space left on device";
if (res == -ENODEV)
err = "No such device";
else if (res == -EINVAL)
err = "Invalid argument";
else if (res == -ENOSPC)
err = "No space left on device";
SetError(err);
}
if (res >= 0) {
auto res = setIps(wgName, Address);
if (res.length() > 0) SetError(res);
if (res.length() > 0)
SetError(res);
}
}
const char* getHostAddress(bool addPort, const sockaddr* addr) {
const char *getHostAddress(bool addPort, const sockaddr *addr) {
char host[4096 + 1], service[512 + 1];
static char buf[sizeof(host) + sizeof(service) + 4];
memset(buf, 0, sizeof(buf));
int ret;
socklen_t addr_len = 0;
if (addr->sa_family == AF_INET) addr_len = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6) addr_len = sizeof(struct sockaddr_in6);
if (addr->sa_family == AF_INET)
addr_len = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6)
addr_len = sizeof(struct sockaddr_in6);
ret = getnameinfo(addr, addr_len, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST);
ret =
getnameinfo(addr, addr_len, host, sizeof(host), service, sizeof(service),
NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST);
if (ret) {
strncpy(buf, gai_strerror(ret), sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
} else {
if (addPort) snprintf(buf, sizeof(buf), (addr->sa_family == AF_INET6 && strchr(host, ':')) ? "[%s]:%s" : "%s:%s", host, service);
else snprintf(buf, sizeof(buf), "%s", host);
if (addPort)
snprintf(buf, sizeof(buf),
(addr->sa_family == AF_INET6 && strchr(host, ':')) ? "[%s]:%s"
: "%s:%s",
host, service);
else
snprintf(buf, sizeof(buf), "%s", host);
}
return buf;
}
@ -311,7 +360,8 @@ std::string keyTo64(const uint8_t *key) {
}
void getConfig::Execute() {
int res; wg_device *device;
int res;
wg_device *device;
if ((res = wg_get_device(&device, strdup(wgName.c_str()))) < 0) {
std::string err = "Cannot get wireguard device, Error code ";
err = err.append(std::to_string(res));
@ -319,18 +369,26 @@ void getConfig::Execute() {
return;
}
if (device->flags & WGDEVICE_HAS_PRIVATE_KEY) privateKey = keyTo64(device->private_key);
if (device->flags & WGDEVICE_HAS_PUBLIC_KEY) publicKey = keyTo64(device->public_key);
if (device->listen_port > 0) portListen = device->listen_port;
if (device->flags & WGDEVICE_HAS_PRIVATE_KEY)
privateKey = keyTo64(device->private_key);
if (device->flags & WGDEVICE_HAS_PUBLIC_KEY)
publicKey = keyTo64(device->public_key);
if (device->listen_port > 0)
portListen = device->listen_port;
// Set Address array and get interface ip addresses
ifaddrs* ptr_ifaddrs = nullptr;
if(getifaddrs(&ptr_ifaddrs) > 0) {
for (ifaddrs* ptr_entry = ptr_ifaddrs; ptr_entry != nullptr; ptr_entry = ptr_entry->ifa_next) {
if (ptr_entry->ifa_addr == nullptr) continue;
else if (strcmp(ptr_entry->ifa_name, wgName.c_str()) != 0) continue;
else if (ptr_entry->ifa_addr->sa_family == AF_INET) Address.push_back(getHostAddress(false, ptr_entry->ifa_addr));
else if (ptr_entry->ifa_addr->sa_family == AF_INET6) Address.push_back(getHostAddress(false, ptr_entry->ifa_addr));
ifaddrs *ptr_ifaddrs = nullptr;
if (getifaddrs(&ptr_ifaddrs) > 0) {
for (ifaddrs *ptr_entry = ptr_ifaddrs; ptr_entry != nullptr;
ptr_entry = ptr_entry->ifa_next) {
if (ptr_entry->ifa_addr == nullptr)
continue;
else if (strcmp(ptr_entry->ifa_name, wgName.c_str()) != 0)
continue;
else if (ptr_entry->ifa_addr->sa_family == AF_INET)
Address.push_back(getHostAddress(false, ptr_entry->ifa_addr));
else if (ptr_entry->ifa_addr->sa_family == AF_INET6)
Address.push_back(getHostAddress(false, ptr_entry->ifa_addr));
}
freeifaddrs(ptr_ifaddrs);
}
@ -338,20 +396,32 @@ void getConfig::Execute() {
wg_peer *peer;
for ((peer) = (device)->first_peer; (peer); (peer) = (peer)->next_peer) {
auto PeerConfig = Peer();
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) PeerConfig.presharedKey = keyTo64(peer->preshared_key);
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL && peer->persistent_keepalive_interval > 0) PeerConfig.keepInterval = peer->persistent_keepalive_interval;
if (peer->endpoint.addr.sa_family == AF_INET||peer->endpoint.addr.sa_family == AF_INET6) PeerConfig.endpoint = getHostAddress(true, &peer->endpoint.addr);
if (peer->last_handshake_time.tv_sec > 0) PeerConfig.last_handshake = peer->last_handshake_time.tv_sec*1000;
if (peer->rx_bytes > 0) PeerConfig.rxBytes = peer->rx_bytes;
if (peer->tx_bytes > 0) PeerConfig.txBytes = peer->tx_bytes;
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
PeerConfig.presharedKey = keyTo64(peer->preshared_key);
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL &&
peer->persistent_keepalive_interval > 0)
PeerConfig.keepInterval = peer->persistent_keepalive_interval;
if (peer->endpoint.addr.sa_family == AF_INET ||
peer->endpoint.addr.sa_family == AF_INET6)
PeerConfig.endpoint = getHostAddress(true, &peer->endpoint.addr);
if (peer->last_handshake_time.tv_sec > 0)
PeerConfig.last_handshake = peer->last_handshake_time.tv_sec * 1000;
if (peer->rx_bytes > 0)
PeerConfig.rxBytes = peer->rx_bytes;
if (peer->tx_bytes > 0)
PeerConfig.txBytes = peer->tx_bytes;
if (peer->first_allowedip) {
wg_allowedip *allowedip;
for ((allowedip) = (peer)->first_allowedip; (allowedip); (allowedip) = (allowedip)->next_allowedip) {
for ((allowedip) = (peer)->first_allowedip; (allowedip);
(allowedip) = (allowedip)->next_allowedip) {
static char buf[INET6_ADDRSTRLEN + 1];
memset(buf, 0, INET6_ADDRSTRLEN + 1);
if (allowedip->family == AF_INET) inet_ntop(AF_INET, &allowedip->ip4, buf, INET6_ADDRSTRLEN);
else if (allowedip->family == AF_INET6) inet_ntop(AF_INET6, &allowedip->ip6, buf, INET6_ADDRSTRLEN);
snprintf(buf + strlen(buf), INET6_ADDRSTRLEN - strlen(buf), "/%d", allowedip->cidr);
if (allowedip->family == AF_INET)
inet_ntop(AF_INET, &allowedip->ip4, buf, INET6_ADDRSTRLEN);
else if (allowedip->family == AF_INET6)
inet_ntop(AF_INET6, &allowedip->ip6, buf, INET6_ADDRSTRLEN);
snprintf(buf + strlen(buf), INET6_ADDRSTRLEN - strlen(buf), "/%d",
allowedip->cidr);
PeerConfig.allowedIPs.push_back(buf);
}
}

@ -1,41 +1,47 @@
#include <napi.h>
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <wireguard-nt/include/wireguard.h>
#include <win/shared.cpp>
#include <windows.h>
#include <tlhelp32.h>
#include "wginterface.hh"
#include <accctrl.h>
#include <aclapi.h>
#include <stdio.h>
#include <stdbool.h>
#include <bcrypt.h>
#include <cfgmgr32.h>
#include <cstdlib>
#include <devguid.h>
#include <fcntl.h>
#include <iostream>
#include <iphlpapi.h>
#include <map>
#include <napi.h>
#include <ndisguid.h>
#include <setupapi.h>
#include <stdbool.h>
#include <stdio.h>
#include <string>
#include <sysinfoapi.h>
#include <tlhelp32.h>
#include <vector>
#include <wgkeys.hh>
#include <win/shared.cpp>
#include <wincrypt.h>
#include <windows.h>
#include <winsock2.h>
#include <winternl.h>
#include <wireguard-nt/include/wireguard.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 <ndisguid.h>
#include "wginterface.hh"
#include <wgkeys.hh>
const DEVPROPKEY devpkey_name = { { 0x65726957, 0x7547, 0x7261, { 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79 } }, DEVPROPID_FIRST_USABLE + 1 };
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_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;
@ -44,55 +50,84 @@ static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
unsigned long maxName() {
return IFNAMSIZ;
}
unsigned long maxName() { return IFNAMSIZ; }
std::string getErrorString(DWORD errorMessageID) {
if (errorMessageID == 0 || errorMessageID < 0) std::string("Error code: ").append(std::to_string(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.
// 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.
// Free the Win32's string's buffer.
LocalFree(messageBuffer);
return std::string("Error code: ").append(std::to_string(errorMessageID)).append(", Message: ").append(message);
return std::string("Error code: ")
.append(std::to_string(errorMessageID))
.append(", Message: ")
.append(message);
}
std::string startAddon(const Napi::Env env) {
if (!IsRunAsAdmin()) return "Run nodejs with administrator privilegies";
if (!IsRunAsAdmin())
return "Run nodejs with administrator privilegies";
auto DLLPATH = env.Global().ToObject().Get("WIREGUARD_DLL_PATH");
if (!(DLLPATH.IsString())) return "Require WIREGUARD_DLL_PATH in Global process";
if (!(DLLPATH.IsString()))
return "Require WIREGUARD_DLL_PATH in Global process";
LPCWSTR dllPath = toLpcwstr(DLLPATH.ToString());
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
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) "Failed to set Functions from WireGuardNT DLL, ")
.append(getErrorString(GetLastError()));
;
}
return "";
}
std::string versionDrive() {
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"getWgVersion", L"Wireguard-tools.js", NULL);
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()));
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));
return ((std::string) "WireGuardNT v")
.append(std::to_string((Version >> 16) & 0xff))
.append(".")
.append(std::to_string((Version >> 0) & 0xff));
}
void listDevices::Execute() {
@ -105,23 +140,30 @@ void listDevices::Execute() {
for (auto &preit : arrayPrefix) {
int ret = 0;
find_handle = FindFirstFile("\\\\.\\pipe\\*", &find_data);
if (find_handle == INVALID_HANDLE_VALUE) continue;
if (find_handle == INVALID_HANDLE_VALUE)
continue;
char *iface;
do {
if (strncmp(preit.c_str(), find_data.cFileName, strlen(preit.c_str()))) continue;
if (strncmp(preit.c_str(), find_data.cFileName, strlen(preit.c_str())))
continue;
iface = find_data.cFileName + strlen(preit.c_str());
listInfo setInfo;
setInfo.tunType = "userspace";
setInfo.pathSock = std::string("\\\\.\\pipe\\").append(preit).append(iface);
setInfo.pathSock =
std::string("\\\\.\\pipe\\").append(preit).append(iface);
deviceNames[std::string(iface)] = setInfo;
} while (FindNextFile(find_handle, &find_data));
FindClose(find_handle);
if (ret < 0) return SetError(std::string("Erro code: ").append(std::to_string(ret)));
if (ret < 0)
return SetError(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) return SetError("Cannot get devices");
HDEVINFO dev_info =
SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, L"SWD\\WireGuard", NULL,
DIGCF_PRESENT, NULL, NULL, NULL);
if (dev_info == INVALID_HANDLE_VALUE)
return SetError("Cannot get devices");
for (DWORD i = 0;; ++i) {
DWORD buf_len;
@ -133,24 +175,37 @@ void listDevices::Execute() {
char *interface_name;
if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
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;
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;
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 (!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)) {
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)) {
listInfo setInfo;
setInfo.tunType = "kernel";
deviceNames[std::string(interface_name)] = setInfo;
@ -162,8 +217,12 @@ void listDevices::Execute() {
void deleteInterface::Execute() {
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(wgName));
if (!Adapter) return SetError("This interface not exists in Wireguard-Tools.js addon!");
if (!(WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_DOWN))) return SetError(std::string("Failed to set down interface, ").append(getErrorString(GetLastError())));
if (!Adapter)
return SetError("This interface not exists in Wireguard-Tools.js addon!");
if (!(WireGuardSetAdapterState(
Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_DOWN)))
return SetError(std::string("Failed to set down interface, ")
.append(getErrorString(GetLastError())));
WireGuardCloseAdapter(Adapter);
}
@ -173,19 +232,22 @@ void deleteInterface::Execute() {
* 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));
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 getConfig::Execute() {
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(wgName));
if (!Adapter) return SetError("This interface not exists in Wireguard-Tools.js addon!");
if (!Adapter)
return SetError("This interface not exists in Wireguard-Tools.js addon!");
NET_LUID InterfaceLuid;
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
try {
for (auto aip : getIpAddr(InterfaceLuid)) Address.push_back(aip);
for (auto aip : getIpAddr(InterfaceLuid))
Address.push_back(aip);
} catch (std::string err) {
return SetError(err);
}
@ -195,18 +257,28 @@ void getConfig::Execute() {
while (!(WireGuardGetConfiguration(Adapter, wg_iface, &buf_len))) {
free(wg_iface);
if (GetLastError() != ERROR_MORE_DATA) return SetError((std::string("Failed get interface config, code: ")).append(std::to_string(GetLastError())));
if (GetLastError() != ERROR_MORE_DATA)
return SetError((std::string("Failed get interface config, code: "))
.append(std::to_string(GetLastError())));
wg_iface = (WIREGUARD_INTERFACE *)malloc(buf_len);
if (!wg_iface) return SetError(((std::string)"Failed get interface config, ").append(std::to_string(-errno)));
if (!wg_iface)
return SetError(((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);
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;
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);
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;
@ -214,24 +286,33 @@ void getConfig::Execute() {
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.last_handshake = (wg_peer->LastHandshake / 10000000 - 11644473600LL) * 1000;
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.last_handshake =
(wg_peer->LastHandshake / 10000000 - 11644473600LL) * 1000;
WIREGUARD_ALLOWED_IP* wg_aip = changePoint<WIREGUARD_PEER, WIREGUARD_ALLOWED_IP>(wg_peer);
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];
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) {
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)));
}
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);
wg_peer = reinterpret_cast<WIREGUARD_PEER *>(wg_aip);
peersVector[pubKey] = peerConfig;
}
@ -241,29 +322,44 @@ void getConfig::Execute() {
void setConfig::Execute() {
DWORD buf_len = sizeof(WIREGUARD_INTERFACE);
for (auto peer : peersVector) {
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_PEER)) return SetError("Buffer overflow");
buf_len += sizeof(WIREGUARD_PEER);
for (auto aip : peer.second.allowedIPs) {
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_ALLOWED_IP)) return SetError("Buffer overflow");
buf_len += sizeof(WIREGUARD_ALLOWED_IP);
}
}
WIREGUARD_INTERFACE *wg_iface = reinterpret_cast<WIREGUARD_INTERFACE*>(calloc(1, buf_len));
if (!wg_iface) return SetError("Cannot alloc buff");
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_PEER))
return SetError("Buffer overflow");
buf_len += sizeof(WIREGUARD_PEER);
for (auto aip : peer.second.allowedIPs) {
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_ALLOWED_IP))
return SetError("Buffer overflow");
buf_len += sizeof(WIREGUARD_ALLOWED_IP);
}
}
WIREGUARD_INTERFACE *wg_iface =
reinterpret_cast<WIREGUARD_INTERFACE *>(calloc(1, buf_len));
if (!wg_iface)
return SetError("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->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 (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);
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);
WIREGUARD_ALLOWED_IP *wg_aip;
WIREGUARD_PEER *wg_peer =
changePoint<WIREGUARD_INTERFACE, WIREGUARD_PEER>(wg_iface);
for (auto __peer : peersVector) {
auto peerPublicKey = __peer.first; auto peerConfig = __peer.second;
auto peerPublicKey = __peer.first;
auto peerConfig = __peer.second;
try {
wgKeys::stringToKey(wg_peer->PublicKey, peerPublicKey);
} catch (std::string &err) {
@ -275,13 +371,18 @@ void setConfig::Execute() {
wg_iface->PeersCount++;
if (peerConfig.removeMe) {
wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_REMOVE);
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) {
try {
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->Flags =
(WIREGUARD_PEER_FLAG)(wg_peer->Flags |
WIREGUARD_PEER_FLAG::
WIREGUARD_PEER_HAS_PRESHARED_KEY);
} catch (std::string &err) {
SetError(err);
goto outEnd;
@ -289,50 +390,79 @@ void setConfig::Execute() {
}
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.keepInterval >= 0)
wg_peer->Flags =
(WIREGUARD_PEER_FLAG)(wg_peer->Flags |
WIREGUARD_PEER_FLAG::
WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE);
if (peerConfig.endpoint.size() > 0) {
try {
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_peer->Flags =
(WIREGUARD_PEER_FLAG)(wg_peer->Flags |
WIREGUARD_PEER_FLAG::
WIREGUARD_PEER_HAS_ENDPOINT);
} catch (std::string &err) {
SetError(std::string("Cannot parse endpoint, ").append(err));
goto outEnd;
}
}
wg_aip = changePoint<WIREGUARD_PEER, WIREGUARD_ALLOWED_IP>(wg_peer);
wg_aip = changePoint<WIREGUARD_PEER, WIREGUARD_ALLOWED_IP>(wg_peer);
for (auto aip : peerConfig.allowedIPs) {
unsigned long cidr = 0;
if (aip.find("/") != std::string::npos) {
cidr = std::stoi(aip.substr(aip.find("/")+1));
cidr = std::stoi(aip.substr(aip.find("/") + 1));
aip = aip.substr(0, aip.find("/"));
}
aip = aip.substr(0, aip.find("/"));
wg_aip->AddressFamily = strchr(aip.c_str(), ':') ? AF_INET6 : AF_INET;
auto status = wg_aip->AddressFamily == AF_INET6 ? inet_pton(wg_aip->AddressFamily, aip.c_str(), &wg_aip->Address.V6) : inet_pton(wg_aip->AddressFamily, aip.c_str(), &wg_aip->Address.V4);
auto status = wg_aip->AddressFamily == AF_INET6
? inet_pton(wg_aip->AddressFamily, aip.c_str(),
&wg_aip->Address.V6)
: inet_pton(wg_aip->AddressFamily, aip.c_str(),
&wg_aip->Address.V4);
if (status == 1) {
if (cidr == 0) cidr = wg_aip->AddressFamily == AF_INET6 ? 128 : 32;
} else continue;
if (cidr == 0)
cidr = wg_aip->AddressFamily == AF_INET6 ? 128 : 32;
} else
continue;
wg_aip->Cidr = cidr;
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_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));
wg_peer = reinterpret_cast<WIREGUARD_PEER *>(((char *)wg_aip));
}
}
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(wgName));
if (!Adapter) Adapter = WireGuardCreateAdapter(toLpcwstr(wgName), L"Wireguard-tools.js", NULL);
if (!Adapter) SetError(((std::string)"Failed to create adapter, ").append(getErrorString(GetLastError())));
else if (!WireGuardSetConfiguration(Adapter, reinterpret_cast<WIREGUARD_INTERFACE*>(wg_iface), buf_len)) {
if (!Adapter)
Adapter =
WireGuardCreateAdapter(toLpcwstr(wgName), L"Wireguard-tools.js", NULL);
if (!Adapter)
SetError(((std::string) "Failed to create adapter, ")
.append(getErrorString(GetLastError())));
else if (!WireGuardSetConfiguration(
Adapter, reinterpret_cast<WIREGUARD_INTERFACE *>(wg_iface),
buf_len)) {
auto status = GetLastError();
SetError(std::string("Failed to set interface config, ").append(getErrorString(status)));
SetError(std::string("Failed to set interface config, ")
.append(getErrorString(status)));
WireGuardCloseAdapter(Adapter);
} else if (!WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_UP)) {
} else if (!WireGuardSetAdapterState(
Adapter,
WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_UP)) {
auto status = GetLastError();
SetError(std::string("Failed to set interface up, ").append(getErrorString(status)));
SetError(std::string("Failed to set interface up, ")
.append(getErrorString(status)));
WireGuardCloseAdapter(Adapter);
} else {
if (Address.size() > 0) {
@ -341,11 +471,19 @@ void setConfig::Execute() {
aip = aip.substr(0, aip.find("/"));
auto family = strchr(aip.c_str(), ':') ? AF_INET6 : AF_INET;
SOCKADDR_INET address;
int status = family == AF_INET ? inet_pton(family, aip.c_str(), &address.Ipv4.sin_addr) : inet_pton(family, aip.c_str(), &address.Ipv6.sin6_addr);
if (status != 1) continue;
int status =
family == AF_INET
? inet_pton(family, aip.c_str(), &address.Ipv4.sin_addr)
: inet_pton(family, aip.c_str(), &address.Ipv6.sin6_addr);
if (status != 1)
continue;
char saddr[INET6_ADDRSTRLEN];
family == AF_INET ? inet_ntop(AF_INET, &address.Ipv4.sin_addr, saddr, INET_ADDRSTRLEN) : inet_ntop(AF_INET6, &address.Ipv6.sin6_addr, saddr, INET6_ADDRSTRLEN);
if (family == AF_INET) IPv4 = std::string(saddr);
family == AF_INET
? inet_ntop(AF_INET, &address.Ipv4.sin_addr, saddr, INET_ADDRSTRLEN)
: inet_ntop(AF_INET6, &address.Ipv6.sin6_addr, saddr,
INET6_ADDRSTRLEN);
if (family == AF_INET)
IPv4 = std::string(saddr);
// else IPv6 = std::string(saddr);
}
@ -353,10 +491,11 @@ void setConfig::Execute() {
NET_LUID InterfaceLuid;
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
auto setStatus = insertIpAddr(InterfaceLuid, IPv4, IPv6);
if (setStatus.size() > 0) SetError(setStatus);
if (setStatus.size() > 0)
SetError(setStatus);
}
}
}
outEnd:
outEnd:
free(wg_iface);
}

@ -1,16 +1,16 @@
#include <napi.h>
#include <iostream>
#include "wginterface.hh"
#include <iostream>
#include <napi.h>
Napi::Object Init(Napi::Env initEnv, Napi::Object exports) {
/// Call Addon
#ifdef ONSTARTADDON
/// Call Addon
#ifdef ONSTARTADDON
auto status = startAddon(initEnv);
if (status.length() >= 1) {
Napi::Error::New(initEnv, status).ThrowAsJavaScriptException();
return exports;
}
#endif
#endif
// Wireguard constants set
const Napi::Object constants = Napi::Object::New(initEnv);
@ -22,84 +22,104 @@ Napi::Object Init(Napi::Env initEnv, Napi::Object exports) {
// Constants
exports.Set("constants", constants);
// Function's
#ifdef SETCONFIG
exports.Set("setConfig", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
const auto wgName = info[0];
const auto wgConfig = info[1];
Napi::Value ret = env.Undefined();
if (!(wgName.IsString())) {
Napi::Error::New(env, "Require wireguard interface name").ThrowAsJavaScriptException();
return env.Undefined();
} else if (wgName.ToString().Utf8Value().length() >= maxName()) {
Napi::Error::New(env, "interface name is so long").ThrowAsJavaScriptException();
return env.Undefined();
} else if (!(wgConfig.IsObject())) {
Napi::Error::New(env, "Require wireguard config object").ThrowAsJavaScriptException();
return env.Undefined();
}
// Function's
#ifdef SETCONFIG
exports.Set(
"setConfig",
Napi::Function::New(
initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
const auto wgName = info[0];
const auto wgConfig = info[1];
Napi::Value ret = env.Undefined();
if (!(wgName.IsString())) {
Napi::Error::New(env, "Require wireguard interface name")
.ThrowAsJavaScriptException();
return env.Undefined();
} else if (wgName.ToString().Utf8Value().length() >= maxName()) {
Napi::Error::New(env, "interface name is so long")
.ThrowAsJavaScriptException();
return env.Undefined();
} else if (!(wgConfig.IsObject())) {
Napi::Error::New(env, "Require wireguard config object")
.ThrowAsJavaScriptException();
return env.Undefined();
}
try {
auto worker = new setConfig(env, wgName.ToString().Utf8Value(), wgConfig.ToObject());
worker->Queue();
return worker->setPromise.Promise();
} catch (const Napi::Error &err) {
err.ThrowAsJavaScriptException();
}
return ret;
}));
#endif
try {
auto worker = new setConfig(env, wgName.ToString().Utf8Value(),
wgConfig.ToObject());
worker->Queue();
return worker->setPromise.Promise();
} catch (const Napi::Error &err) {
err.ThrowAsJavaScriptException();
}
return ret;
}));
#endif
#ifdef DELIFACE
exports.Set("deleteInterface", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
const auto wgName = info[0];
if (!(wgName.IsString())) {
Napi::Error::New(env, "Require wireguard interface name").ThrowAsJavaScriptException();
return env.Undefined();
} else if (wgName.ToString().Utf8Value().length() >= maxName()) {
Napi::Error::New(env, "interface name is so long").ThrowAsJavaScriptException();
return env.Undefined();
}
#ifdef DELIFACE
exports.Set("deleteInterface",
Napi::Function::New(
initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
const auto wgName = info[0];
if (!(wgName.IsString())) {
Napi::Error::New(env, "Require wireguard interface name")
.ThrowAsJavaScriptException();
return env.Undefined();
} else if (wgName.ToString().Utf8Value().length() >=
maxName()) {
Napi::Error::New(env, "interface name is so long")
.ThrowAsJavaScriptException();
return env.Undefined();
}
auto worker = new deleteInterface(env, wgName.ToString().Utf8Value());
worker->Queue();
return worker->deletePromise.Promise();
}));
#endif
auto worker =
new deleteInterface(env, wgName.ToString().Utf8Value());
worker->Queue();
return worker->deletePromise.Promise();
}));
#endif
#ifdef GETCONFIG
exports.Set("getConfig", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
const auto wgName = info[0];
if (!(wgName.IsString())) {
Napi::Error::New(env, "Require wireguard interface name").ThrowAsJavaScriptException();
return env.Undefined();
} else if (wgName.ToString().Utf8Value().length() >= maxName()) {
Napi::Error::New(env, "interface name is so long").ThrowAsJavaScriptException();
return env.Undefined();
}
#ifdef GETCONFIG
exports.Set(
"getConfig",
Napi::Function::New(
initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
const auto wgName = info[0];
if (!(wgName.IsString())) {
Napi::Error::New(env, "Require wireguard interface name")
.ThrowAsJavaScriptException();
return env.Undefined();
} else if (wgName.ToString().Utf8Value().length() >= maxName()) {
Napi::Error::New(env, "interface name is so long")
.ThrowAsJavaScriptException();
return env.Undefined();
}
try {
auto worker = new getConfig(env, wgName.ToString().Utf8Value());
worker->Queue();
return worker->getPromise.Promise();
} catch (const Napi::Error &err) {
err.ThrowAsJavaScriptException();
}
return env.Undefined();
}));
#endif
try {
auto worker = new getConfig(env, wgName.ToString().Utf8Value());
worker->Queue();
return worker->getPromise.Promise();
} catch (const Napi::Error &err) {
err.ThrowAsJavaScriptException();
}
return env.Undefined();
}));
#endif
#ifdef LISTDEV
exports.Set("listDevices", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
auto worker = new listDevices(env);
worker->Queue();
return worker->listDevicesPromise.Promise();
}));
#endif
#ifdef LISTDEV
exports.Set("listDevices",
Napi::Function::New(
initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
auto worker = new listDevices(env);
worker->Queue();
return worker->listDevicesPromise.Promise();
}));
#endif
return exports;
}
NODE_API_MODULE(addon, Init);

@ -1,36 +1,37 @@
#include <string>
#include <vector>
#include <wireguard-nt/include/wireguard.h>
#include <windows.h>
#include <ws2ipdef.h>
#include <ws2def.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <netioapi.h>
#include <iphlpapi.h>
#include <chrono>
#include <thread>
#include <iostream>
#include <iphlpapi.h>
#include <netioapi.h>
#include <string>
#include <thread>
#include <vector>
#include <windows.h>
#include <winsock2.h>
#include <wireguard-nt/include/wireguard.h>
#include <ws2def.h>
#include <ws2ipdef.h>
#include <ws2tcpip.h>
// Function to check if the current user has administrator privileges
bool IsRunAsAdmin()
{
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)) {
if (GetTokenInformation(hToken, TokenElevation, &Elevation,
sizeof(Elevation), &cbSize)) {
fRet = Elevation.TokenIsElevated;
}
}
if (hToken) CloseHandle(hToken);
if (hToken)
CloseHandle(hToken);
return !!fRet;
}
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);
wchar_t *wString = new wchar_t[s.length() + 1];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, wString, s.length() + 1);
return wString;
}
@ -38,98 +39,119 @@ 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;
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);
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;
int ret, retries = parse_dns_retries();
char *begin, *end;
auto mmutable = strdup(value.c_str());
if (!mmutable) throw std::string("strdup");
if (!value.size()) {
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) {
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);
throw std::string("Unable to find matching brace of endpoint: ")
.append(value);
}
*end++ = '\0';
if (*end++ != ':' || !*end) {
*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)) {
} 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';
}
*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));
}
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);
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 parseEndpoint(SOCKADDR_INET *input) {
if (!(input->si_family == AF_INET || input->si_family == AF_INET6)) return "";
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);
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)));
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)));
}
std::string insertIpAddr(NET_LUID InterfaceLuid, std::string IPv4, std::string IPv6) {
std::string insertIpAddr(NET_LUID InterfaceLuid, std::string IPv4,
std::string IPv6) {
NET_IFINDEX ind;
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) return "Cannot get interface index";
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR)
return "Cannot get interface index";
// IPv4
if (IPv4.size() > 0) {
@ -137,10 +159,13 @@ std::string insertIpAddr(NET_LUID InterfaceLuid, std::string IPv4, std::string I
ULONG NTEInstance = 0;
UINT iaIPAddress;
inet_pton(AF_INET, IPv4.c_str(), &iaIPAddress);
auto status = AddIPAddress(iaIPAddress, NULL, ind, &NTEContext, &NTEInstance);
auto status =
AddIPAddress(iaIPAddress, NULL, ind, &NTEContext, &NTEInstance);
if (status != NO_ERROR) {
if (status == 5010) {
} else return std::string("Cannot set IPv4 interface, error code: ").append(std::to_string(status));
} else
return std::string("Cannot set IPv4 interface, error code: ")
.append(std::to_string(status));
}
}
@ -155,25 +180,31 @@ std::string insertIpAddr(NET_LUID InterfaceLuid, std::string IPv4, std::string I
std::vector<std::string> getIpAddr(NET_LUID InterfaceLuid) {
NET_IFINDEX ind;
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR)
throw std::string("Cannot get interface index");
std::vector<std::string> ips;
IP_ADAPTER_INFO *pAdapterInfo;
IP_ADAPTER_INFO *pAdapterInfo;
ULONG ulOutBufLen;
DWORD dwRetVal;
pAdapterInfo = (IP_ADAPTER_INFO *) malloc( sizeof(IP_ADAPTER_INFO) );
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 (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));
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) ips.push_back(std::string(pAdapter->IpAddressList.IpAddress.String).append("/32"));
if (pAdapter->Index == ind)
ips.push_back(
std::string(pAdapter->IpAddressList.IpAddress.String).append("/32"));
pAdapter = pAdapter->Next;
}
if (pAdapterInfo) free(pAdapterInfo);
if (pAdapterInfo)
free(pAdapterInfo);
return ips;
}

@ -5,10 +5,10 @@
#pragma once
#include <winsock2.h>
#include <windows.h>
#include <ipexport.h>
#include <ifdef.h>
#include <ipexport.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2ipdef.h>
#ifdef __cplusplus
@ -16,22 +16,23 @@ 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
#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_
#define _Post_maybenull_
#endif
#pragma warning(push)
#pragma warning(disable : 4324) /* structure was padded due to alignment specifier */
#pragma warning( \
disable : 4324) /* structure was padded due to alignment specifier */
/**
* A handle representing WireGuard adapter
@ -41,85 +42,93 @@ 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 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 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.
* @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.
* @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);
_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.
* @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.
* @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);
_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.
* Releases WireGuard adapter resources and, if adapter was created with
* WireGuardCreateAdapter, removes adapter.
*
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter.
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or
* WireGuardOpenAdapter.
*/
typedef VOID(WINAPI WIREGUARD_CLOSE_ADAPTER_FUNC)(_In_opt_ WIREGUARD_ADAPTER_HANDLE Adapter);
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.
* @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);
BOOL(WINAPI WIREGUARD_DELETE_DRIVER_FUNC)(VOID);
/**
* Returns the LUID of the adapter.
*
* @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter
* @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);
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:
* @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);
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 */
typedef enum {
WIREGUARD_LOG_INFO, /**< Informational */
WIREGUARD_LOG_WARN, /**< Warning */
WIREGUARD_LOG_ERR /**< Error */
} WIREGUARD_LOGGER_LEVEL;
/**
@ -127,179 +136,203 @@ typedef enum
*
* @param Level Message level.
*
* @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC.
* @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_ 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.
* @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);
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. */
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.
* 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 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.
* @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);
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 */
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.
* 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 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.
* @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);
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 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.
* @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);
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 */
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 */
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 */
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 */
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 */
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 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.
* @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);
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 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
* @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);
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)