Big code refactoring #10
							
								
								
									
										49
									
								
								.vscode/c_cpp_properties.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										49
									
								
								.vscode/c_cpp_properties.json
									
									
									
									
										vendored
									
									
								
							| @@ -1,22 +1,31 @@ | ||||
| { | ||||
|     "configurations": [ | ||||
|         { | ||||
|             "name": "Mac", | ||||
|             "includePath": [ | ||||
|                 "${workspaceFolder}/node_modules/node-addon-api", | ||||
|                 "/usr/local/include/node", | ||||
|                 "${workspaceFolder}/**", | ||||
|                 "${workspaceFolder}/addon" | ||||
|             ], | ||||
|             "defines": [], | ||||
|             "macFrameworkPath": [ | ||||
|                 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks" | ||||
|             ], | ||||
|             "compilerPath": "/usr/bin/clang", | ||||
|             "cStandard": "c17", | ||||
|             "cppStandard": "c++17", | ||||
|             "intelliSenseMode": "macos-clang-x64" | ||||
|         } | ||||
|     ], | ||||
|     "version": 4 | ||||
|   "configurations": [ | ||||
|     { | ||||
|       "name": "Mac", | ||||
|       "includePath": [ | ||||
|         "${workspaceFolder}/node_modules/node-addon-api", | ||||
|         "/usr/local/include/node", | ||||
|         "${workspaceFolder}/**", | ||||
|         "${workspaceFolder}/addon" | ||||
|       ], | ||||
|       "defines": [], | ||||
|       "macFrameworkPath": [ | ||||
|         "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks" | ||||
|       ], | ||||
|       "compilerPath": "/usr/bin/clang", | ||||
|       "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 { | ||||
|   | ||||
							
								
								
									
										42
									
								
								addon/wg.hh
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								addon/wg.hh
									
									
									
									
									
								
							| @@ -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 }); | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user