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",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-x64"
},
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/node_modules/node-addon-api",
"/usr/include/node",
"${workspaceFolder}/**",
"${workspaceFolder}/addon"
]
}
],
"version": 4

@ -10,6 +10,7 @@ extern "C" {
#include <arpa/inet.h>
#include <time.h>
#include <unistd.h>
#include <cstring>
std::string getWireguardVersion() {
return "Kernel";
@ -96,6 +97,7 @@ void WireguardConfig::getWireguardConfig() {
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);
else continue;
PeerConfig.allowedIPs.push_back(std::string(buf).append("/").append(std::to_string(allowedip->cidr)));
}
}
@ -105,12 +107,11 @@ void WireguardConfig::getWireguardConfig() {
void WireguardConfig::setWireguardConfig() {
int status;
if (this->name.length() == 0) throw std::string("Set wireguard name!");
else if (this->name.length() > IFNAMSIZ) throw std::string("Wireguard interface name is long, max name length is ").append(std::to_string(IFNAMSIZ));
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));
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!");
strncpy(wgConfig->name, this->name.c_str(), this->name.length());
@ -135,8 +136,7 @@ void WireguardConfig::setWireguardConfig() {
}
for (auto &PeerConfig : this->Peers) {
wg_peer* peer;
peer = (wg_peer*)malloc(sizeof(wg_peer));
auto peer = new wg_peer({});
peer->flags = wg_peer_flags::WGPEER_HAS_PUBLIC_KEY;
wgKeys::stringToKey(peer->public_key, PeerConfig.first);
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];
end = strchr(Endpoint, ']');
if (!end) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
delete wgConfig;
free(Endpoint);
throw std::string("Unable to find matching brace of endpoint");
return;
}
*end++ = '\0';
if (*end++ != ':' || !*end) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
delete wgConfig;
free(Endpoint);
throw std::string("Unable to find port of endpoint");
return;
@ -176,8 +176,8 @@ void WireguardConfig::setWireguardConfig() {
begin = Endpoint;
end = strrchr(Endpoint, ':');
if (!end || !*(end + 1)) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
delete wgConfig;
free(Endpoint);
throw std::string("Unable to find port of endpoint");
}
@ -192,8 +192,8 @@ void WireguardConfig::setWireguardConfig() {
ret == EAI_NODATA ||
#endif
(retries >= 0 && !retries--)) {
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
delete wgConfig;
free(Endpoint);
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");
@ -216,30 +216,29 @@ void WireguardConfig::setWireguardConfig() {
}
} else {
freeaddrinfo(resolved);
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
delete wgConfig;
free(Endpoint);
throw std::string("Neither IPv4 nor IPv6 address found");
}
freeaddrinfo(resolved);
// Free memory
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { free(peer); }
free(wgConfig);
for ((peer) = (wgConfig)->first_peer; (peer); (peer) = (peer)->next_peer) { delete peer; }
delete wgConfig;
free(Endpoint);
}
// Set allowed IPs
if (PeerConfig.second.allowedIPs.size() > 0) {
wg_allowedip *newAllowedIP;
peer->flags = (wg_peer_flags)(peer->flags|WGPEER_REPLACE_ALLOWEDIPS);
for (const auto &Ip : PeerConfig.second.allowedIPs.getIpParsed()) {
newAllowedIP = (wg_allowedip*)(malloc(sizeof(wg_allowedip)));
auto newAllowedIP = new wg_allowedip({});
newAllowedIP->cidr = Ip.Mask;
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 {
free(newAllowedIP);
delete newAllowedIP;
continue;
}
@ -258,10 +257,10 @@ void WireguardConfig::setWireguardConfig() {
// Free memory
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);
free(peer);
for (wg_allowedip *newAllowedIP = peer->first_allowedip; newAllowedIP; newAllowedIP = newAllowedIP->next_allowedip) delete newAllowedIP;
delete peer;
}
free(wgConfig);
delete wgConfig;
// Return status to tool
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 {
const Napi::Env env = info.Env();
if (!(info[0].IsObject())) Napi::Error::New(env, "Set wireguard config!").ThrowAsJavaScriptException();
try {
SetConfig *worker = new SetConfig(env, info[0].ToObject());
worker->Queue();
return worker->NodePromise.Promise();
} catch (std::string &err) {
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 {

@ -72,8 +72,45 @@ class SetConfig : public WireguardConfig, public Promised {
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("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->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
const Napi::Object peersObj = Napi::Object::New(env);
for (auto &__peer : this->Peers) {
std::cout << "script\n";
std::string publicKey = __peer.first;
if (publicKey.length() != Base64WgKeyLength) continue;
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);
for (auto &ip : config.allowedIPs) ips.Set(ips.Length(), ip);
peersObj.Set("allowedIPs", ips);
peerConfig.Set("allowedIPs", ips);
peersObj.Set(publicKey, peerConfig);
}

@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include <map>
#include <iostream>
extern const int wgKeyLength;
extern const int Base64WgKeyLength;
@ -50,7 +51,7 @@ class IpManeger : public std::vector<std::string> {
if (maskStart == std::string::npos) xTop.Address = ip;
else {
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!");
}
xTop.Proto = isIPv6 ? 6 : 4;
@ -63,7 +64,7 @@ class IpManeger : public std::vector<std::string> {
IpReference nTop;
auto maskStart = ipAddrr->find("/");
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);
}
return xTops;
@ -117,6 +118,7 @@ class WireguardConfig {
WireguardConfig() {
this->portListen = 0;
this->fwmark = 0;
this->replacePeers = false;
}
/** Wireguard interface name */

@ -34,8 +34,8 @@
},
"scripts": {
"install": "rebory prebuild",
"dev": "rebory build -DP",
"test": "rebory build -D && node --no-warnings --loader ts-node/esm src/index_test.js",
"dev": "rebory build",
"test": "rebory build && node --no-warnings --loader ts-node/esm src/index_test.js",
"prepack": "tsc --build --clean && tsc --build",
"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 });
});