Big code refactoring #10

Merged
Sirherobrine23 merged 15 commits from code_refactoring into main 2024-03-15 04:08:27 +00:00
5 changed files with 286 additions and 59 deletions
Showing only changes of commit 089873e9b0 - Show all commits

@ -8,6 +8,9 @@ std::string getWireguardVersion() {
void IpManeger::SetInInterface(std::string interfaceName) {
throw std::string("Use userspace module");
}
void IpManeger::GetInInterface(std::string interfaceName) {
throw std::string("Use userspace module");
}
void WireguardConfig::setWireguardConfig() {
throw std::string("Use userspace module");

@ -11,6 +11,15 @@ extern "C" {
#include <time.h>
#include <unistd.h>
#include <cstring>
#include <stdlib.h>
#include <stdio.h>
#include <asm/types.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <malloc.h>
#include <string.h>
#include <iostream>
std::string getWireguardVersion() {
return "Kernel";
@ -39,6 +48,26 @@ void WireguardDevices::deleteInterface(std::string wgName) {
}
}
std::string HostAdresses(bool addPort, const sockaddr* addr) {
char host[4096 + 1], service[512 + 1];
static char buf[sizeof(host) + sizeof(service) + 4];
memset(buf, 0, sizeof(buf));
int ret;
socklen_t addr_len = 0;
if (addr->sa_family == AF_INET) addr_len = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6) addr_len = sizeof(struct sockaddr_in6);
ret = getnameinfo(addr, addr_len, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST);
if (ret) {
strncpy(buf, gai_strerror(ret), sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
} else {
if (addPort) snprintf(buf, sizeof(buf), (addr->sa_family == AF_INET6 && strchr(host, ':')) ? "[%s]:%s" : "%s:%s", host, service);
else snprintf(buf, sizeof(buf), "%s", host);
}
return std::string(buf);
};
void WireguardConfig::getWireguardConfig() {
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));
@ -48,37 +77,7 @@ void WireguardConfig::getWireguardConfig() {
if (devConfig->flags & WGDEVICE_HAS_PRIVATE_KEY) privateKey = wgKeys::toString(devConfig->private_key);
if (devConfig->flags & WGDEVICE_HAS_PUBLIC_KEY) publicKey = wgKeys::toString(devConfig->public_key);
if (devConfig->flags & WGDEVICE_HAS_LISTEN_PORT) portListen = devConfig->listen_port;
auto HostAdresses = [](bool addPort, const sockaddr* addr) -> std::string {
char host[4096 + 1], service[512 + 1];
static char buf[sizeof(host) + sizeof(service) + 4];
memset(buf, 0, sizeof(buf));
int ret;
socklen_t addr_len = 0;
if (addr->sa_family == AF_INET) addr_len = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6) addr_len = sizeof(struct sockaddr_in6);
ret = getnameinfo(addr, addr_len, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST);
if (ret) {
strncpy(buf, gai_strerror(ret), sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
} else {
if (addPort) snprintf(buf, sizeof(buf), (addr->sa_family == AF_INET6 && strchr(host, ':')) ? "[%s]:%s" : "%s:%s", host, service);
else snprintf(buf, sizeof(buf), "%s", host);
}
return std::string(buf);
};
ifaddrs* ptr_ifaddrs = nullptr;
if(getifaddrs(&ptr_ifaddrs) > 0) {
for (ifaddrs* ptr_entry = ptr_ifaddrs; ptr_entry != nullptr; ptr_entry = ptr_entry->ifa_next) {
if (ptr_entry->ifa_addr == nullptr) continue;
else if (strcmp(ptr_entry->ifa_name, this->name.c_str()) != 0) continue;
else if (ptr_entry->ifa_addr->sa_family == AF_INET) this->interfaceAddress.addIPMask(HostAdresses(false, ptr_entry->ifa_addr));
else if (ptr_entry->ifa_addr->sa_family == AF_INET6) this->interfaceAddress.addIPMask(HostAdresses(false, ptr_entry->ifa_addr));
}
freeifaddrs(ptr_ifaddrs);
}
this->interfaceAddress.GetInInterface(this->name);
for ((peer) = (devConfig)->first_peer; (peer); (peer) = (peer)->next_peer) {
auto PeerConfig = Peer();
@ -90,16 +89,13 @@ void WireguardConfig::getWireguardConfig() {
PeerConfig.rxBytes = peer->rx_bytes;
PeerConfig.txBytes = peer->tx_bytes;
if (peer->first_allowedip) {
wg_allowedip *allowedip;
for ((allowedip) = (peer)->first_allowedip; (allowedip); (allowedip) = (allowedip)->next_allowedip) {
static char buf[INET6_ADDRSTRLEN + 1];
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)));
}
wg_allowedip *allowedip;
for ((allowedip) = (peer)->first_allowedip; (allowedip); (allowedip) = (allowedip)->next_allowedip) {
static char buf[INET6_ADDRSTRLEN + 1];
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);
PeerConfig.allowedIPs.push_back(std::string(buf).append("/").append(std::to_string(allowedip->cidr)));
}
this->Peers[wgKeys::toString(peer->public_key)] = PeerConfig;
}
@ -229,22 +225,19 @@ void WireguardConfig::setWireguardConfig() {
free(Endpoint);
}
// Set allowed IPs
if (PeerConfig.second.allowedIPs.size() > 0) {
peer->flags = (wg_peer_flags)(peer->flags|WGPEER_REPLACE_ALLOWEDIPS);
for (const auto &Ip : PeerConfig.second.allowedIPs.getIpParsed()) {
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 {
delete newAllowedIP;
continue;
}
if (peer->first_allowedip) newAllowedIP->next_allowedip = peer->first_allowedip;
peer->first_allowedip = newAllowedIP;
for (const auto Ip : PeerConfig.second.allowedIPs.getIpParsed()) {
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) peer->flags = (wg_peer_flags)(peer->flags|WGPEER_REPLACE_ALLOWEDIPS);
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 {
delete newAllowedIP;
continue;
}
if (peer->first_allowedip) newAllowedIP->next_allowedip = peer->first_allowedip;
peer->first_allowedip = newAllowedIP;
}
}
@ -269,6 +262,232 @@ void WireguardConfig::setWireguardConfig() {
}
}
void IpManeger::GetInInterface(std::string interfaceName) {
ifaddrs* ptr_ifaddrs = nullptr;
if(getifaddrs(&ptr_ifaddrs) >= 0) {
for (ifaddrs* ptr_entry = ptr_ifaddrs; ptr_entry != nullptr; ptr_entry = ptr_entry->ifa_next) {
if (ptr_entry->ifa_addr == nullptr) continue;
else if (strcmp(ptr_entry->ifa_name, interfaceName.c_str()) != 0) continue;
else if (ptr_entry->ifa_addr->sa_family == AF_INET) this->addIPMask(HostAdresses(false, ptr_entry->ifa_addr));
else if (ptr_entry->ifa_addr->sa_family == AF_INET6) this->addIPMask(HostAdresses(false, ptr_entry->ifa_addr));
}
freeifaddrs(ptr_ifaddrs);
}
}
struct rtnl_handle {
int fd;
struct sockaddr_nl local;
struct sockaddr_nl peer;
__u32 seq;
__u32 dump;
};
typedef struct {
__u8 family;
__u8 bytelen;
__s16 bitlen;
__u32 flags;
__u32 data[8];
} inet_prefix;
// This function is to open the netlink socket as the name suggests.
int netlink_open(struct rtnl_handle* rth) {
int addr_len;
memset(rth, 0, sizeof(rth));
// Creating the netlink socket of family NETLINK_ROUTE
rth->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (rth->fd < 0)
{
perror("cannot open netlink socket");
return -1;
}
memset(&rth->local, 0, sizeof(rth->local));
rth->local.nl_family = AF_NETLINK;
rth->local.nl_groups = 0;
// Binding the netlink socket
if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0)
{
perror("cannot bind netlink socket");
return -1;
}
addr_len = sizeof(rth->local);
if (getsockname(rth->fd, (struct sockaddr*)&rth->local, (socklen_t*) &addr_len) < 0)
{
perror("cannot getsockname");
return -1;
}
if (addr_len != sizeof(rth->local))
{
fprintf(stderr, "wrong address lenght %d\n", addr_len);
return -1;
}
if (rth->local.nl_family != AF_NETLINK)
{
fprintf(stderr, "wrong address family %d\n", rth->local.nl_family);
return -1;
}
rth->seq = time(NULL);
return 0;
}
// This function does the actual reading and writing to the netlink socket
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, unsigned groups, struct nlmsghdr *answer) {
int status;
struct nlmsghdr *h;
struct sockaddr_nl nladdr;
// Forming the iovector with the netlink packet.
struct iovec iov = { (void*)n, n->nlmsg_len };
char buf[8192];
// Forming the message to be sent.
struct msghdr msg = { (void*)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 };
// Filling up the details of the netlink socket to be contacted in the
// kernel.
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = peer;
nladdr.nl_groups = groups;
n->nlmsg_seq = ++rtnl->seq;
if (answer == NULL)
n->nlmsg_flags |= NLM_F_ACK;
// Actual sending of the message, status contains success/failure
status = sendmsg(rtnl->fd, &msg, 0);
if (status < 0)
return -1;
}
// This is the utility function for adding the parameters to the packet.
int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) {
int len = RTA_LENGTH(alen);
struct rtattr *rta;
if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
return -1;
rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
rta->rta_type = type;
rta->rta_len = len;
memcpy(RTA_DATA(rta), data, alen);
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
return 0;
}
int get_addr_1(inet_prefix *addr, const char *name, int family) {
memset(addr, 0, sizeof(*addr));
if (strcmp(name, "default") == 0 ||
strcmp(name, "all") == 0 ||
strcmp(name, "any") == 0) {
if (family == AF_DECnet)
return -1;
addr->family = family;
addr->bytelen = (family == AF_INET6 ? 16 : 4);
addr->bitlen = -1;
return 0;
}
if (strchr(name, ':')) {
addr->family = AF_INET6;
if (family != AF_UNSPEC && family != AF_INET6)
return -1;
if (inet_pton(AF_INET6, name, addr->data) <= 0)
return -1;
addr->bytelen = 16;
addr->bitlen = -1;
return 0;
}
addr->family = AF_INET;
if (family != AF_UNSPEC && family != AF_INET)
return -1;
struct in_addr inAddr;
inet_pton(AF_INET, name, (void*)&inAddr);
memcpy(&addr->data,&inAddr.s_addr, sizeof(inAddr.s_addr));
// if (get_addr_ipv4((__u8 *)addr->data, name) <= 0)
// return -1;
addr->bytelen = 4;
addr->bitlen = -1;
return 0;
}
int get_prefix(inet_prefix *dst, char *arg, int family) {
int err;
unsigned plen;
memset(dst, 0, sizeof(*dst));
if (strcmp(arg, "default") == 0 ||
strcmp(arg, "any") == 0 ||
strcmp(arg, "all") == 0) {
if (family == AF_DECnet)
return -1;
dst->family = family;
dst->bytelen = 0;
dst->bitlen = 0;
return 0;
}
err = get_addr_1(dst, arg, family);
if (err == 0) {
switch(dst->family) {
case AF_INET6:
dst->bitlen = 128;
break;
case AF_DECnet:
dst->bitlen = 16;
break;
default:
case AF_INET:
dst->bitlen = 32;
}
}
return err;
}
void IpManeger::SetInInterface(std::string interfaceName) {
if (this->size() == 0) return;
if (!(WireguardDevices().exist(interfaceName))) throw std::string("Wireguard interface not exists!");
int status; unsigned int ifa_index; wg_device *devConfig;;
if ((status = wg_get_device(&devConfig, interfaceName.c_str())) < 0) throw std::string("It was not possible to get the Wireguard interface settings, code: ").append(std::to_string(status));
ifa_index = devConfig->ifindex;
free(devConfig);
struct rtnl_handle * rth;
rth = (rtnl_handle*)malloc(sizeof(rtnl_handle));
netlink_open(rth);
for (const auto ip : this->getIpParsed()) {
inet_prefix lcl;
// structure of the netlink packet.
struct {
struct nlmsghdr n;
struct ifaddrmsg ifa;
char buf[1024];
} req;
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
req.n.nlmsg_type = RTM_NEWADDR;
req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST;
req.ifa.ifa_family = ip.Proto == 4 ? AF_INET : AF_INET6;
req.ifa.ifa_prefixlen = ip.Mask;
req.ifa.ifa_index = ifa_index ; // get the loopback index
req.ifa.ifa_scope = 0 ;
get_prefix(&lcl, ip.Address.c_str(), req.ifa.ifa_family);
if (req.ifa.ifa_family == AF_UNSPEC) req.ifa.ifa_family = lcl.family;
struct in_addr inAddr;
inet_pton(req.ifa.ifa_family, ip.Address.c_str(), (void*)&inAddr);
addattr_l(&req.n, sizeof(req), IFA_LOCAL, &inAddr, sizeof(inAddr));
if (rtnl_talk(rth, &req.n, 0, 0, NULL) < 0); //throw std::string("Cannot set interface ip!");
}
}

@ -78,6 +78,7 @@ class SetConfig : public WireguardConfig, public Promised {
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("replacePeers") && config.Get("replacePeers").IsBoolean()) this->replacePeers = config.Get("replacePeers").ToBoolean().Value();
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>());

@ -41,6 +41,7 @@ typedef struct IpReference {
class IpManeger : public std::vector<std::string> {
public:
void SetInInterface(std::string interfaceName);
void GetInInterface(std::string interfaceName);
void addIPMask(std::string ip) {
IpReference xTop;
@ -60,11 +61,12 @@ class IpManeger : public std::vector<std::string> {
std::vector<IpReference> getIpParsed() {
std::vector<IpReference> xTops;
for (auto ipAddrr = this->begin(); ipAddrr != this->end(); ++ipAddrr) {
for (auto ipAddrr = this->begin(); ipAddrr != this->end(); ++ipAddrr) {
IpReference nTop;
auto maskStart = ipAddrr->find("/");
nTop.Address = ipAddrr->substr(0, maskStart);
nTop.Mask = std::stoi(ipAddrr->substr(maskStart+1).c_str());
nTop.Proto = (nTop.Address.find(":") != std::string::npos) ? 6 : 4;
xTops.push_back(nTop);
}
return xTops;

@ -6,8 +6,10 @@ await test("Wireguard interface", async t => {
const config: SetConfig = {
name: "wg0",
privateKey: await privateKey(),
replacePeers: true,
address: [
"10.66.66.1/32"
"10.66.66.1/32",
"fd42:42:42::1/128"
],
peers: {}
};
@ -21,7 +23,7 @@ await test("Wireguard interface", async t => {
]
};
console.dir(config, { depth: null });
await Kernel.setConfig(config);
console.dir(await Kernel.getConfig(config.name), { depth: null });
await Kernel.deleteInterface(config.name);
});