diff --git a/.github/workflows/testProject.yml b/.github/workflows/testProject.yml index f5f2a2f..743599f 100644 --- a/.github/workflows/testProject.yml +++ b/.github/workflows/testProject.yml @@ -47,7 +47,7 @@ jobs: run: | tsc --build --clean tsc --build - sudo -E mocha ./ + sudo -E mocha ./src - name: Upload generate interface uses: actions/upload-artifact@v3 diff --git a/addons/tools/wginterface-dummy.cpp b/addons/tools/wginterface-dummy.cpp index c72ac46..6a04a4c 100644 --- a/addons/tools/wginterface-dummy.cpp +++ b/addons/tools/wginterface-dummy.cpp @@ -12,11 +12,6 @@ unsigned long maxName() { } void listDevices::Execute() {} - -void setConfig::Execute() { - SetError("Use userpace implementation, kernel only on linux!"); -} - -void getConfig::Execute() { - SetError("Use userpace implementation, kernel only on linux!"); -} \ No newline at end of file +void deleteInterface::Execute() {} +void setConfig::Execute() {} +void getConfig::Execute() {} \ No newline at end of file diff --git a/addons/tools/wginterface-linux.cpp b/addons/tools/wginterface-linux.cpp index 0dc14e0..4ece61d 100644 --- a/addons/tools/wginterface-linux.cpp +++ b/addons/tools/wginterface-linux.cpp @@ -28,34 +28,15 @@ extern "C" { #include "linux/wireguard.h" } -#ifndef SETCONFIG -#define SETCONFIG -#endif -#ifndef GETCONFIG -#define GETCONFIG -#endif -#ifndef LISTDEV -#define LISTDEV -#endif +#define SETCONFIG 1 +#define GETCONFIG 1 +#define LISTDEV 1 +#define DELIFACE 1 unsigned long maxName() { return IFNAMSIZ; } -Napi::Value listDevicesSync(const Napi::CallbackInfo& info) { - const Napi::Env env = info.Env(); - size_t len; - char *device_name, *devicesList = wg_list_device_names(); - if (!devicesList) { - Napi::Error::New(env, "Unable to get device names").ThrowAsJavaScriptException(); - return env.Undefined(); - } - const Napi::Array devicesArray = Napi::Array::New(env); - for ((device_name) = (devicesList), (len) = 0; ((len) = strlen(device_name)); (device_name) += (len) + 1) devicesArray.Set(devicesArray.Length(), Napi::String::New(env, device_name)); - free(devicesList); - return devicesArray; -} - void listDevices::Execute() { char *device_name, *devicesList = wg_list_device_names(); if (!devicesList) SetError("Unable to get device names"); @@ -85,6 +66,26 @@ int setInterface(std::string wgName) { return len; } +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) { + 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)); + SetError(err); + } + break; + } + } + free(devicesList); + } +} + void setConfig::Execute() { int res = setInterface(wgName); if (res < 0) { diff --git a/addons/tools/wginterface.cpp b/addons/tools/wginterface.cpp index e5f5823..087a0ee 100644 --- a/addons/tools/wginterface.cpp +++ b/addons/tools/wginterface.cpp @@ -30,6 +30,30 @@ Napi::Value setConfigAsync(const Napi::CallbackInfo &info) { return env.Undefined(); } +Napi::Value deleteInterfaceAsync(const Napi::CallbackInfo &info) { + const Napi::Env env = info.Env(); + const auto wgName = info[0]; + const auto callback = info[1]; + 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 (!(callback.IsFunction())) { + Napi::Error::New(env, "Require callback").ThrowAsJavaScriptException(); + return env.Undefined(); + } + + try { + const auto delInterWorker = new deleteInterface(callback.As(), wgName.ToString().Utf8Value()); + delInterWorker->Queue(); + } catch (const Napi::Error &err) { + err.ThrowAsJavaScriptException(); + } + return env.Undefined(); +} + Napi::Value getConfigAsync(const Napi::CallbackInfo &info) { const Napi::Env env = info.Env(); const auto wgName = info[0]; @@ -78,13 +102,19 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) { // Constants exports.Set("constants", constants); - // async function + // Function's #ifdef SETCONFIG exports.Set("setConfigAsync", Napi::Function::New(env, setConfigAsync)); #endif + + #ifdef DELIFACE + exports.Set("deleteInterfaceAsync", Napi::Function::New(env, deleteInterfaceAsync)); + #endif + #ifdef GETCONFIG exports.Set("getConfigAsync", Napi::Function::New(env, getConfigAsync)); #endif + #ifdef LISTDEV exports.Set("listDevicesAsync", Napi::Function::New(env, listDevicesAsync)); #endif diff --git a/addons/tools/wginterface.hh b/addons/tools/wginterface.hh index 96924ea..f486d94 100644 --- a/addons/tools/wginterface.hh +++ b/addons/tools/wginterface.hh @@ -6,12 +6,24 @@ unsigned long maxName(); -/* -Esta função consegela o loop event +class deleteInterface : public Napi::AsyncWorker { + private: + std::string wgName; + public: + deleteInterface(const Napi::Function &callback, std::string name): AsyncWorker(callback), wgName(name) {} + ~deleteInterface() {} + void OnOK() override { + Napi::HandleScope scope(Env()); + Callback().Call({ Env().Undefined() }); + }; + void OnError(const Napi::Error &e) override { + Napi::HandleScope scope(Env()); + Callback().Call({ e.Value() }); + } -Pegar todas as interfaces do Wireguard e retorna em forma de String sendo tratado pelo Node.js quando retornado. -*/ -Napi::Value listDevicesSync(const Napi::CallbackInfo& info); + // Set platform Execute script + void Execute() override; +}; class listDevices : public Napi::AsyncWorker { private: diff --git a/binding.gyp b/binding.gyp index dacb9c0..c5c9d7c 100644 --- a/binding.gyp +++ b/binding.gyp @@ -62,7 +62,8 @@ "defines": [ "LISTDEV", "GETCONFIG", - "SETCONFIG" + "SETCONFIG", + "DELIFACE" ], "sources": [ "addons/tools/linux/wireguard.c", diff --git a/examples/addPeer/index.mjs b/examples/addPeer/index.mjs index 446bff6..671c821 100644 --- a/examples/addPeer/index.mjs +++ b/examples/addPeer/index.mjs @@ -1,4 +1,4 @@ -import { listDevices, parseWgDevice, addDevice, utils } from "wireguard-tools.js"; +import { listDevices, parseWgDevice, addDevice, wgConfig, utils } from "wireguard-tools.js"; const deviceName = (await listDevices()).at(-1); if (!deviceName) { console.info("Create wireguard interface"); @@ -6,14 +6,12 @@ if (!deviceName) { } // Get current config -const currentConfig = await parseWgDevice(deviceName); +const currentConfig = new wgConfig(await parseWgDevice(deviceName)); // Create Peer -const peerKey = await utils.keygenAsync(true); -currentConfig.peers[peerKey.public] = { presharedKey: peerKey.preshared, allowedIPs: [ utils.ipManipulation.randomIp("10.22.66.1/24", Object.keys(currentConfig.peers).map(k => currentConfig.peers[k].allowedIPs).flat(2).filter(Boolean)) ] }; -currentConfig.peers[peerKey.public].allowedIPs.push(utils.ipManipulation.toV6(currentConfig.peers[peerKey.public].allowedIPs.at(0))); -console.log("Add %O peer", peerKey.public); +const peer = await currentConfig.newPeer(true); +console.log("Add %O peer", peer.publicKey); // Set to interface await addDevice(deviceName, currentConfig); -console.dir(currentConfig, { colors: true, depth: null }); \ No newline at end of file +console.dir(currentConfig, { depth: null }); \ No newline at end of file diff --git a/package.json b/package.json index 12be895..31d677c 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ }, "scripts": { "install": "node libs/build.mjs", - "test": "mocha ./", + "test": "mocha ./src", "dev": "tsc --build --clean && tsc --build && node libs/build.mjs build", "prebuildify": "node libs/build.mjs build --auto", "prepack": "tsc --build --clean && tsc --build && npm run prebuildify", diff --git a/src/wginterface.test.ts b/src/wginterface.test.ts index e53b526..d9a7572 100644 --- a/src/wginterface.test.ts +++ b/src/wginterface.test.ts @@ -48,5 +48,6 @@ if (process.platform !== "win32" && (userInfo()).gid === 0) { }); it("After list", async () => await Bridge.listDevices()); + it("Delete", async () => await Bridge.deleteInterface(interfaceName)); }); } diff --git a/src/wginterface.ts b/src/wginterface.ts index 4ac86c7..8853927 100644 --- a/src/wginterface.ts +++ b/src/wginterface.ts @@ -81,7 +81,7 @@ export class wgConfig extends Map { allowedIPs: [IPv4, IPv6], presharedKey: withPreshared ? peerKey.preshared : undefined }); - return this.get(peerKey.public); + return Object.assign({}, { publicKey: peerKey.public }, this.get(peerKey.public)); } toJSON(): wireguardInterface { @@ -178,6 +178,16 @@ export async function getConfig(deviceName: string): Promise return config.toJSON(); } +/** + * Delete wg interface if possible + * @param deviceName - Wireguard interface name. + * @returns + */ +export async function deleteInterface(deviceName: string): Promise { + if (typeof wg_binding.deleteInterfaceAsync === "function") return promisify(wg_binding.deleteInterfaceAsync)(deviceName); + return fs.rm(path.join(defaultPath, deviceName).concat(".sock"), { force: true }); +} + /** * Set Wireguard interface config. * @param deviceName - Wireguard interface name.