Skip to content

Commit

Permalink
fix linux update interface and delete and create test to interface
Browse files Browse the repository at this point in the history
Signed-off-by: Matheus Sampaio Queiroga <[email protected]>
  • Loading branch information
Sirherobrine23 committed Feb 21, 2024
1 parent 1c9d30a commit 5d9851d
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 117 deletions.
8 changes: 2 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ jobs:
- uses: actions/checkout@v4
name: Checkout

- name: "Setup zig"
uses: korandoru/setup-zig@v1
with:
zig-version: "0.11.0"

- uses: actions/setup-node@v4
name: Setup Node.js
with:
Expand All @@ -37,10 +32,11 @@ jobs:
- name: Run tests
env:
FORCE_COLOR: "true"
run: node --no-warnings --loader ts-node/esm src/index_test.ts
run: sudo "$(command -v node)" --no-warnings --loader ts-node/esm src/index_test.ts

build_addon:
runs-on: ubuntu-latest
needs: test_js
strategy:
matrix:
node_version: [ 16.x, 17.x, 18.x, 19.x, 20.x, 21.x ]
Expand Down
4 changes: 2 additions & 2 deletions addons/tools/linux/wireguard.c
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,7 @@ static int add_del_iface(const char *ifname, bool add)

nlh = mnl_nlmsg_put_header(rtnl_buffer);
nlh->nlmsg_type = add ? RTM_NEWLINK : RTM_DELLINK;
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (add ? NLM_F_CREATE | NLM_F_EXCL : 0);
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (add ? NLM_F_CREATE | NLM_F_EXCL : RTM_DELLINK);
nlh->nlmsg_seq = time(NULL);
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
ifm->ifi_family = AF_UNSPEC;
Expand All @@ -1049,7 +1049,7 @@ static int add_del_iface(const char *ifname, bool add)
goto cleanup;
}
if (mnl_cb_run(rtnl_buffer, len, nlh->nlmsg_seq, mnl_socket_get_portid(nl), NULL, NULL) < 0) {
ret = -errno;
ret = -errno;
goto cleanup;
}
ret = 0;
Expand Down
154 changes: 47 additions & 107 deletions addons/tools/wginterface-linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,77 +28,8 @@ extern "C" {
#include "linux/wireguard.h"
}

#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */

std::string getKernelMesage(int errStatus) {
std::string message = std::string("Error code: ").append(std::to_string(errStatus));
if (errStatus == -EPERM) message = std::string("Operation not permitted, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENOENT) message = std::string("No such file or directory, code: ").append(std::to_string(errStatus));
else if (errStatus == -ESRCH) message = std::string("No such process, code: ").append(std::to_string(errStatus));
else if (errStatus == -EINTR) message = std::string("Interrupted system call, code: ").append(std::to_string(errStatus));
else if (errStatus == -EIO) message = std::string("I/O error, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENXIO) message = std::string("No such device or address, code: ").append(std::to_string(errStatus));
else if (errStatus == -E2BIG) message = std::string("Argument list too long, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENOEXEC) message = std::string("Exec format error, code: ").append(std::to_string(errStatus));
else if (errStatus == -EBADF) message = std::string("Bad file number, code: ").append(std::to_string(errStatus));
else if (errStatus == -ECHILD) message = std::string("No child processes, code: ").append(std::to_string(errStatus));
else if (errStatus == -EAGAIN) message = std::string("Try again, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENOMEM) message = std::string("Out of memory, code: ").append(std::to_string(errStatus));
else if (errStatus == -EACCES) message = std::string("Permission denied, code: ").append(std::to_string(errStatus));
else if (errStatus == -EFAULT) message = std::string("Bad address, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENOTBLK) message = std::string("Block device required, code: ").append(std::to_string(errStatus));
else if (errStatus == -EBUSY) message = std::string("Device or resource busy, code: ").append(std::to_string(errStatus));
else if (errStatus == -EEXIST) message = std::string("File exists, code: ").append(std::to_string(errStatus));
else if (errStatus == -EXDEV) message = std::string("Cross-device link, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENODEV) message = std::string("No such device, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENOTDIR) message = std::string("Not a directory, code: ").append(std::to_string(errStatus));
else if (errStatus == -EISDIR) message = std::string("Is a directory, code: ").append(std::to_string(errStatus));
else if (errStatus == -EINVAL) message = std::string("Invalid argument, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENFILE) message = std::string("File table overflow, code: ").append(std::to_string(errStatus));
else if (errStatus == -EMFILE) message = std::string("Too many open files, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENOTTY) message = std::string("Not a typewriter, code: ").append(std::to_string(errStatus));
else if (errStatus == -ETXTBSY) message = std::string("Text file busy, code: ").append(std::to_string(errStatus));
else if (errStatus == -EFBIG) message = std::string("File too large, code: ").append(std::to_string(errStatus));
else if (errStatus == -ENOSPC) message = std::string("No space left on device, code: ").append(std::to_string(errStatus));
else if (errStatus == -ESPIPE) message = std::string("Illegal seek, code: ").append(std::to_string(errStatus));
else if (errStatus == -EROFS) message = std::string("Read-only file system, code: ").append(std::to_string(errStatus));
else if (errStatus == -EMLINK) message = std::string("Too many links, code: ").append(std::to_string(errStatus));
else if (errStatus == -EPIPE) message = std::string("Broken pipe, code: ").append(std::to_string(errStatus));
else if (errStatus == -EDOM) message = std::string("Math argument out of domain of func, code: ").append(std::to_string(errStatus));
else if (errStatus == -ERANGE) message = std::string("Math result not representable, code: ").append(std::to_string(errStatus));
return message;
}

Expand All @@ -110,55 +41,71 @@ 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");
size_t len;
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;
class List {
public:
std::vector<std::string> devs;

List() {}
~List() {
devs.clear();
}
free(devicesList);
}

int setInterface(std::string wgName) {
size_t len = 0;
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) {
if (device_name == wgName.c_str()) {
createInterface = false;
break;
}
}
void getAll() {
char *device_name, *devicesList = wg_list_device_names();
if (!devicesList) throw std::string("Unable to get device names");
size_t len;
for ((device_name) = (devicesList), (len) = 0; ((len) = strlen(device_name)); (device_name) += (len) + 1) devs.push_back(std::string(device_name));
free(devicesList);
len = 0;
if (createInterface) len = wg_add_device(wgName.c_str());
}

return len;
bool exist(std::string ifname) {
this->getAll();
for (auto wg : devs) if (wg == ifname) return true;
return false;
}
};

void listDevices::Execute() {
List l;
try {
l.getAll();
for (auto ifname : l.devs) {
listInfo setInfo;
setInfo.tunType = "kernel";
deviceNames[ifname] = setInfo;
}
} catch (std::string err) {
SetError(err);
}
l.~List();
}

void deleteInterface::Execute() {
int status = wg_del_device(wgName.c_str());
if (status < 0) SetError(std::string("Cannot delete interface, code status: ").append(std::to_string(status)));
}

int createInterface(std::string &wgName) {
bool createInterface = true;
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) SetError(getKernelMesage(len));
if (std::string(device_name) == wgName) {
createInterface = false;
break;
}
}
free(devicesList);
}
if (createInterface) return wg_add_device(wgName.c_str());
return 0;
}

void setConfig::Execute() {
int res = setInterface(wgName);
if (res < 0 && res != EEXIST) {
SetError(getKernelMesage(res));
int res = createInterface(wgName);
if (res < 0) {
SetError(std::string("Cannot create wireguard interface, Code: ").append(std::to_string(res)));
return;
}

Expand Down Expand Up @@ -328,14 +275,7 @@ void setConfig::Execute() {
}

// Set interface config
if ((res = wg_set_device(deviceStruct)) < 0) {
SetError(getKernelMesage(res));
}

if (res >= 0) {
auto res = setIps(wgName, Address);
if (res.length() > 0) SetError(res);
}
if ((res = wg_set_device(deviceStruct)) < 0) SetError(getKernelMesage(res));
}

const char* getHostAddress(bool addPort, const sockaddr* addr) {
Expand Down Expand Up @@ -367,7 +307,7 @@ std::string keyTo64(const uint8_t *key) {
void getConfig::Execute() {
int res; wg_device *device;
if ((res = wg_get_device(&device, strdup(wgName.c_str()))) < 0) {
SetError(getKernelMesage(res));
SetError(std::string("Device not exists or cannot get config from this interface!, code error: ").append(std::to_string(res)));
return;
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wireguard-tools.js",
"version": "2.0.0",
"version": "2.0.1",
"description": "Control your wireguard interface from node.js, not a wireguard-tools/wg wrapper!",
"private": false,
"type": "module",
Expand Down
3 changes: 2 additions & 1 deletion src/index_test.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import "./quick_test.js";
import "./key_test.js";
import "./key_test.js";
import "./wginterface_test.js";
54 changes: 54 additions & 0 deletions src/wginterface_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import test from "node:test";
import { setConfig, deleteInterface, WgConfigSet, getConfig } from "./wginterface.js";
import { publicKey } from "./key.js";
import { userInfo } from "os";

if (process.platform === "win32" || process.platform === "linux" && (userInfo().uid === 0)) {
test("Wireguard configuration", async t => {
// Config base
const peer1Key = 'EKgSatFzZtsv1qFJ6gE8HqfuA+tXzW+7vDeVc7Xaa2E=', peer2Key = '4BSvgiM9j5jjuR0Vg3gbqTFD5+CyuOU2K2kJE5+cakQ=',
config: WgConfigSet = {
privateKey: "4GTKsUfzodunTXaHtY/u+JhQN1D2CP1Sc+4D1VmpylY=",
address: [
"10.66.124.1/32"
],
peers: {}
};

config.peers[publicKey(peer1Key)] = {
allowedIPs: [
"10.66.124.2"
]
}

await t.test("Set config in interface", async () => {
await setConfig("wg23", config);
});

await t.test("Get config in interface", async () => {
const __config = await getConfig("wg23");
if (!__config.peers[publicKey(peer1Key)]) throw new Error("Not exist peer 1!");
});

config.peers[publicKey(peer1Key)].removeMe = true;
config.peers[publicKey(peer2Key)] = {
allowedIPs: [
"10.66.124.3"
]
}

await t.test("Set config in interface", async () => {
await setConfig("wg23", config);
});

await t.test("Get config in interface", async () => {
const __config = await getConfig("wg23");
if (__config.peers[publicKey(peer1Key)]) throw new Error("Invalid config get!");
if (!__config.peers[publicKey(peer2Key)]) throw new Error("Not exist peer 2!");
});

await t.test("Delete interface", async () => {
await deleteInterface("wg23");
});
});
}

0 comments on commit 5d9851d

Please sign in to comment.