Big code refactoring #10

Merged
Sirherobrine23 merged 15 commits from code_refactoring into main 2024-03-15 04:08:27 +00:00
7 changed files with 125 additions and 51 deletions
Showing only changes of commit d3ea7b39cd - Show all commits

@ -16,6 +16,15 @@
"cStandard": "c17", "cStandard": "c17",
"cppStandard": "c++17", "cppStandard": "c++17",
"intelliSenseMode": "macos-clang-x64" "intelliSenseMode": "macos-clang-x64"
},
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/node_modules/node-addon-api",
"/usr/include/node",
"${workspaceFolder}/**",
"${workspaceFolder}/addon"
]
} }
], ],
"version": 4 "version": 4

@ -10,6 +10,7 @@ extern "C" {
#include <arpa/inet.h> #include <arpa/inet.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <cstring>
std::string getWireguardVersion() { std::string getWireguardVersion() {
return "Kernel"; return "Kernel";
@ -96,6 +97,7 @@ void WireguardConfig::getWireguardConfig() {
memset(buf, 0, INET6_ADDRSTRLEN + 1); memset(buf, 0, INET6_ADDRSTRLEN + 1);
if (allowedip->family == AF_INET) inet_ntop(AF_INET, &allowedip->ip4, buf, INET6_ADDRSTRLEN); 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); else if (allowedip->family == AF_INET6) inet_ntop(AF_INET6, &allowedip->ip6, buf, INET6_ADDRSTRLEN);
else continue;
PeerConfig.allowedIPs.push_back(std::string(buf).append("/").append(std::to_string(allowedip->cidr))); PeerConfig.allowedIPs.push_back(std::string(buf).append("/").append(std::to_string(allowedip->cidr)));
} }
} }
@ -105,12 +107,11 @@ void WireguardConfig::getWireguardConfig() {
void WireguardConfig::setWireguardConfig() { void WireguardConfig::setWireguardConfig() {
int status; int status;
if (this->name.length() == 0) throw std::string("Set wireguard name!"); if (this->name.length() > IFNAMSIZ) throw std::string("Wireguard interface name is long, max name length is ").append(std::to_string(IFNAMSIZ));
else if (this->name.length() > IFNAMSIZ) throw std::string("Wireguard interface name is long, max name length is ").append(std::to_string(IFNAMSIZ));
else if (!(WireguardDevices().exist(this->name)) && (status = wg_add_device(this->name.c_str())) < 0) throw std::string("Unable to create Wireguard interface, code: ").append(std::to_string(status)); else if (!(WireguardDevices().exist(this->name)) && (status = wg_add_device(this->name.c_str())) < 0) throw std::string("Unable to create Wireguard interface, code: ").append(std::to_string(status));
if (this->privateKey.length() != Base64WgKeyLength) throw std::string("Set Wireguard interface private key!"); if (this->privateKey.length() != Base64WgKeyLength) throw std::string("Set Wireguard interface private key!");
auto wgConfig = (wg_device*)malloc(sizeof(wg_device)); auto wgConfig = new wg_device({});
if (!wgConfig) throw std::string("Cannot alloc memory to set interface configuration!"); if (!wgConfig) throw std::string("Cannot alloc memory to set interface configuration!");
strncpy(wgConfig->name, this->name.c_str(), this->name.length()); strncpy(wgConfig->name, this->name.c_str(), this->name.length());
@ -135,8 +136,7 @@ void WireguardConfig::setWireguardConfig() {
} }
for (auto &PeerConfig : this->Peers) { for (auto &PeerConfig : this->Peers) {
wg_peer* peer; auto peer = new wg_peer({});
peer = (wg_peer*)malloc(sizeof(wg_peer));
peer->flags = wg_peer_flags::WGPEER_HAS_PUBLIC_KEY; peer->flags = wg_peer_flags::WGPEER_HAS_PUBLIC_KEY;
wgKeys::stringToKey(peer->public_key, PeerConfig.first); wgKeys::stringToKey(peer->public_key, PeerConfig.first);
if (PeerConfig.second.removeMe) peer->flags = (wg_peer_flags)(peer->flags|wg_peer_flags::WGPEER_REMOVE_ME); if (PeerConfig.second.removeMe) peer->flags = (wg_peer_flags)(peer->flags|wg_peer_flags::WGPEER_REMOVE_ME);
@ -158,16 +158,16 @@ void WireguardConfig::setWireguardConfig() {
begin = &Endpoint[1]; begin = &Endpoint[1];
end = strchr(Endpoint, ']'); end = strchr(Endpoint, ']');
if (!end) { if (!end) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); } for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
free(wgConfig); delete wgConfig;
free(Endpoint); free(Endpoint);
throw std::string("Unable to find matching brace of endpoint"); throw std::string("Unable to find matching brace of endpoint");
return; return;
} }
*end++ = '\0'; *end++ = '\0';
if (*end++ != ':' || !*end) { if (*end++ != ':' || !*end) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); } for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
free(wgConfig); delete wgConfig;
free(Endpoint); free(Endpoint);
throw std::string("Unable to find port of endpoint"); throw std::string("Unable to find port of endpoint");
return; return;
@ -176,8 +176,8 @@ void WireguardConfig::setWireguardConfig() {
begin = Endpoint; begin = Endpoint;
end = strrchr(Endpoint, ':'); end = strrchr(Endpoint, ':');
if (!end || !*(end + 1)) { if (!end || !*(end + 1)) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); } for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
free(wgConfig); delete wgConfig;
free(Endpoint); free(Endpoint);
throw std::string("Unable to find port of endpoint"); throw std::string("Unable to find port of endpoint");
} }
@ -192,8 +192,8 @@ void WireguardConfig::setWireguardConfig() {
ret == EAI_NODATA || ret == EAI_NODATA ||
#endif #endif
(retries >= 0 && !retries--)) { (retries >= 0 && !retries--)) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); } for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
free(wgConfig); delete wgConfig;
free(Endpoint); free(Endpoint);
fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), PeerConfig.second.endpoint.c_str()); fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), PeerConfig.second.endpoint.c_str());
throw std::string("Unable to resolve endpoint"); throw std::string("Unable to resolve endpoint");
@ -216,30 +216,29 @@ void WireguardConfig::setWireguardConfig() {
} }
} else { } else {
freeaddrinfo(resolved); freeaddrinfo(resolved);
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); } for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
free(wgConfig); delete wgConfig;
free(Endpoint); free(Endpoint);
throw std::string("Neither IPv4 nor IPv6 address found"); throw std::string("Neither IPv4 nor IPv6 address found");
} }
freeaddrinfo(resolved); freeaddrinfo(resolved);
// Free memory // Free memory
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); } for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
free(wgConfig); delete wgConfig;
free(Endpoint); free(Endpoint);
} }
// Set allowed IPs // Set allowed IPs
if (PeerConfig.second.allowedIPs.size() > 0) { if (PeerConfig.second.allowedIPs.size() > 0) {
wg_allowedip *newAllowedIP;
peer->flags = (wg_peer_flags)(peer->flags|WGPEER_REPLACE_ALLOWEDIPS); peer->flags = (wg_peer_flags)(peer->flags|WGPEER_REPLACE_ALLOWEDIPS);
for (const auto &Ip : PeerConfig.second.allowedIPs.getIpParsed()) { for (const auto &Ip : PeerConfig.second.allowedIPs.getIpParsed()) {
newAllowedIP = (wg_allowedip*)(malloc(sizeof(wg_allowedip))); auto newAllowedIP = new wg_allowedip({});
newAllowedIP->cidr = Ip.Mask; newAllowedIP->cidr = Ip.Mask;
if (Ip.Proto == 6 && inet_pton(AF_INET6, Ip.Address.c_str(), &newAllowedIP->ip6) == 1) newAllowedIP->family = AF_INET6; if (Ip.Proto == 6 && inet_pton(AF_INET6, Ip.Address.c_str(), &newAllowedIP->ip6) == 1) newAllowedIP->family = AF_INET6;
else if (Ip.Proto == 4 && inet_pton(AF_INET, Ip.Address.c_str(), &newAllowedIP->ip4) == 1) newAllowedIP->family = AF_INET; else if (Ip.Proto == 4 && inet_pton(AF_INET, Ip.Address.c_str(), &newAllowedIP->ip4) == 1) newAllowedIP->family = AF_INET;
else { else {
free(newAllowedIP); delete newAllowedIP;
continue; continue;
} }
@ -258,10 +257,10 @@ void WireguardConfig::setWireguardConfig() {
// Free memory // Free memory
for (wg_peer* peer = wgConfig->first_peer; peer; peer = peer->next_peer) { for (wg_peer* peer = wgConfig->first_peer; peer; peer = peer->next_peer) {
for (wg_allowedip *newAllowedIP = peer->first_allowedip; newAllowedIP; newAllowedIP = newAllowedIP->next_allowedip) free(newAllowedIP); for (wg_allowedip *newAllowedIP = peer->first_allowedip; newAllowedIP; newAllowedIP = newAllowedIP->next_allowedip) delete newAllowedIP;
free(peer); delete peer;
} }
free(wgConfig); delete wgConfig;
// Return status to tool // Return status to tool
if (status < 0) throw std::string("Unable to configure settings, code: ").append(std::to_string(status)); if (status < 0) throw std::string("Unable to configure settings, code: ").append(std::to_string(status));

@ -37,14 +37,15 @@ Napi::Object StartAddon(const Napi::Env env, const Napi::Object exports) {
exports.Set("setConfig", Napi::Function::New(env, [](const Napi::CallbackInfo &info) -> Napi::Value { exports.Set("setConfig", Napi::Function::New(env, [](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env(); const Napi::Env env = info.Env();
if (!(info[0].IsObject())) Napi::Error::New(env, "Set wireguard config!").ThrowAsJavaScriptException();
try { try {
SetConfig *worker = new SetConfig(env, info[0].ToObject()); SetConfig *worker = new SetConfig(env, info[0].ToObject());
worker->Queue(); worker->Queue();
return worker->NodePromise.Promise(); return worker->NodePromise.Promise();
} catch (std::string &err) { } catch (std::string &err) {
Napi::Error::New(env, err).ThrowAsJavaScriptException(); Napi::Error::New(env, err).ThrowAsJavaScriptException();
return env.Undefined();
} }
return env.Undefined();
})); }));
exports.Set("getConfig", Napi::Function::New(env, [](const Napi::CallbackInfo &info) -> Napi::Value { exports.Set("getConfig", Napi::Function::New(env, [](const Napi::CallbackInfo &info) -> Napi::Value {

@ -72,8 +72,45 @@ class SetConfig : public WireguardConfig, public Promised {
SetConfig(const Napi::Env &env, const Napi::Object config): Promised(env) { SetConfig(const Napi::Env &env, const Napi::Object config): Promised(env) {
if (!(config.Has("name"))) throw std::string("Set wireguard interface name!"); if (!(config.Has("name"))) throw std::string("Set wireguard interface name!");
if (!(config.Has("privateKey"))) throw std::string("Set wireguard private key!"); if (!(config.Has("privateKey") && config.Get("privateKey").IsString())) throw std::string("Set wireguard private key!");
this->name = config.Get("name").ToString().Utf8Value(); this->name = config.Get("name").ToString().Utf8Value();
this->privateKey = config.Get("privateKey").ToString().Utf8Value();
if (config.Has("publicKey") && config.Get("publicKey").IsString() && config.Get("publicKey").ToString().Utf8Value().length() == Base64WgKeyLength) this->publicKey = config.Get("publicKey").ToString().Utf8Value();
if (config.Has("portListen") && config.Get("portListen").IsNumber() && config.Get("portListen").ToNumber().Int32Value() >= 0) this->portListen = config.Get("portListen").ToNumber().Int32Value();
if (config.Has("fwmark") && config.Get("fwmark").IsNumber() && config.Get("fwmark").ToNumber().Int32Value() >= 0) this->fwmark = config.Get("fwmark").ToNumber().Int32Value();
if (config.Has("address") && config.Get("address").IsArray() && config.Get("address").As<Napi::Array>().Length() > 0) {
const Napi::Array Addrs(config.Get("address").As<Napi::Array>());
for (unsigned int AddrIndex = 0; AddrIndex < Addrs.Length(); AddrIndex++) {
if (!(Addrs[AddrIndex].IsString())) continue;
this->interfaceAddress.addIPMask(Addrs[AddrIndex].ToString().Utf8Value());
}
}
if (config.Has("peers") && config.Get("peers").IsObject()) {
const Napi::Object PeersObject(config.Get("peers").ToObject());
const Napi::Array PeersKeys(PeersObject.GetPropertyNames());
for (unsigned int peerIndex = 0; peerIndex < PeersKeys.Length(); peerIndex++) {
if (!(PeersObject.Get(PeersKeys[peerIndex].ToString()).IsObject())) continue;
const std::string publicKey(PeersKeys[peerIndex].ToString().Utf8Value());
const Napi::Object peerConfig(PeersObject.Get(publicKey).ToObject());
Peer peer;
if (peerConfig.Has("removeMe") && peerConfig.Get("removeMe").IsBoolean() && peerConfig.Get("removeMe").As<Napi::Boolean>().Value()) peer.removeMe = true;
else {
if (peerConfig.Has("presharedKey") && peerConfig.Get("presharedKey").IsString() && peerConfig.Get("presharedKey").ToString().Utf8Value().length() == Base64WgKeyLength) peer.presharedKey = peerConfig.Get("presharedKey").ToString().Utf8Value();
if (peerConfig.Has("keepInterval") && peerConfig.Get("keepInterval").IsNumber() && peerConfig.Get("keepInterval").ToNumber().Int32Value() > 0) peer.keepInterval = peerConfig.Get("keepInterval").ToNumber().Int32Value();
if (peerConfig.Has("endpoint") && peerConfig.Get("endpoint").IsString() && peerConfig.Get("endpoint").ToString().Utf8Value().length() == Base64WgKeyLength) peer.endpoint = peerConfig.Get("endpoint").ToString().Utf8Value();
if (peerConfig.Has("allowedIPs") && peerConfig.Get("allowedIPs").IsArray()) {
const Napi::Array ips = peerConfig.Get("allowedIPs").As<Napi::Array>();
for (unsigned int ipIndex = 0; ipIndex < ips.Length(); ipIndex++) peer.allowedIPs.addIPMask(ips[ipIndex].ToString().Utf8Value());
}
}
// Set peer in map
this->Peers[publicKey] = peer;
}
}
} }
}; };
@ -108,7 +145,6 @@ class GetConfig : public WireguardConfig, public Promised {
// Peers // Peers
const Napi::Object peersObj = Napi::Object::New(env); const Napi::Object peersObj = Napi::Object::New(env);
for (auto &__peer : this->Peers) { for (auto &__peer : this->Peers) {
std::cout << "script\n";
std::string publicKey = __peer.first; std::string publicKey = __peer.first;
if (publicKey.length() != Base64WgKeyLength) continue; if (publicKey.length() != Base64WgKeyLength) continue;
const Napi::Object peerConfig = Napi::Object::New(env); const Napi::Object peerConfig = Napi::Object::New(env);
@ -124,7 +160,7 @@ class GetConfig : public WireguardConfig, public Promised {
const Napi::Array ips = Napi::Array::New(env); const Napi::Array ips = Napi::Array::New(env);
for (auto &ip : config.allowedIPs) ips.Set(ips.Length(), ip); for (auto &ip : config.allowedIPs) ips.Set(ips.Length(), ip);
peersObj.Set("allowedIPs", ips); peerConfig.Set("allowedIPs", ips);
peersObj.Set(publicKey, peerConfig); peersObj.Set(publicKey, peerConfig);
} }

@ -4,6 +4,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <iostream>
extern const int wgKeyLength; extern const int wgKeyLength;
extern const int Base64WgKeyLength; extern const int Base64WgKeyLength;
@ -50,7 +51,7 @@ class IpManeger : public std::vector<std::string> {
if (maskStart == std::string::npos) xTop.Address = ip; if (maskStart == std::string::npos) xTop.Address = ip;
else { else {
xTop.Address = ip.substr(0, maskStart); xTop.Address = ip.substr(0, maskStart);
xTop.Mask = atoi(ip.substr(maskStart+1).c_str()); xTop.Mask = std::stoi(ip.substr(maskStart+1).c_str());
if (!isIPv6 && xTop.Mask > 32) throw std::string("Set valid mask to ipv4 address!"); if (!isIPv6 && xTop.Mask > 32) throw std::string("Set valid mask to ipv4 address!");
} }
xTop.Proto = isIPv6 ? 6 : 4; xTop.Proto = isIPv6 ? 6 : 4;
@ -63,7 +64,7 @@ class IpManeger : public std::vector<std::string> {
IpReference nTop; IpReference nTop;
auto maskStart = ipAddrr->find("/"); auto maskStart = ipAddrr->find("/");
nTop.Address = ipAddrr->substr(0, maskStart); nTop.Address = ipAddrr->substr(0, maskStart);
nTop.Mask = atoi(ipAddrr->substr(maskStart+1).c_str()); nTop.Mask = std::stoi(ipAddrr->substr(maskStart+1).c_str());
xTops.push_back(nTop); xTops.push_back(nTop);
} }
return xTops; return xTops;
@ -117,6 +118,7 @@ class WireguardConfig {
WireguardConfig() { WireguardConfig() {
this->portListen = 0; this->portListen = 0;
this->fwmark = 0; this->fwmark = 0;
this->replacePeers = false;
} }
/** Wireguard interface name */ /** Wireguard interface name */

@ -34,8 +34,8 @@
}, },
"scripts": { "scripts": {
"install": "rebory prebuild", "install": "rebory prebuild",
"dev": "rebory build -DP", "dev": "rebory build",
"test": "rebory build -D && node --no-warnings --loader ts-node/esm src/index_test.js", "test": "rebory build && node --no-warnings --loader ts-node/esm src/index_test.js",
"prepack": "tsc --build --clean && tsc --build", "prepack": "tsc --build --clean && tsc --build",
"postpack": "tsc --build --clean" "postpack": "tsc --build --clean"
}, },

@ -0,0 +1,27 @@
import test from "node:test";
import { Kernel, SetConfig } from "./wginterface.js";
import { presharedKey, privateKey, publicKey } from "./key.js";
await test("Wireguard interface", async t => {
const config: SetConfig = {
name: "wg0",
privateKey: await privateKey(),
address: [
"10.66.66.1/32"
],
peers: {}
};
const peer1 = await privateKey();
config.peers[publicKey(peer1)] = {
keepInterval: 15,
presharedKey: await presharedKey(),
allowedIPs: [
"10.66.66.2/32"
]
};
console.dir(config, { depth: null });
await Kernel.setConfig(config);
console.dir(await Kernel.getConfig(config.name), { depth: null });
});