|
|
|
@ -17,7 +17,7 @@ extern "C" {
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <linux/netlink.h>
|
|
|
|
|
#include <linux/rtnetlink.h>
|
|
|
|
|
#include <malloc.h>
|
|
|
|
|
// #include <malloc.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
@ -74,9 +74,9 @@ void WireguardConfig::getWireguardConfig() {
|
|
|
|
|
else if (!(WireguardDevices().exist(this->name))) throw std::string("Wireguard interface not exist");
|
|
|
|
|
int status; wg_device *devConfig; wg_peer *peer;
|
|
|
|
|
if ((status = wg_get_device(&devConfig, this->name.c_str())) < 0) throw std::string("It was not possible to get the Wireguard interface settings, code: ").append(std::to_string(status));
|
|
|
|
|
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;
|
|
|
|
|
if (devConfig->flags & WGDEVICE_HAS_PRIVATE_KEY) this->privateKey = wgKeys::toString(devConfig->private_key);
|
|
|
|
|
if (devConfig->flags & WGDEVICE_HAS_PUBLIC_KEY) this->publicKey = wgKeys::toString(devConfig->public_key);
|
|
|
|
|
if (devConfig->flags & WGDEVICE_HAS_LISTEN_PORT) this->portListen = devConfig->listen_port;
|
|
|
|
|
this->interfaceAddress.GetInInterface(this->name);
|
|
|
|
|
|
|
|
|
|
for ((peer) = (devConfig)->first_peer; (peer); (peer) = (peer)->next_peer) {
|
|
|
|
@ -291,48 +291,28 @@ typedef struct {
|
|
|
|
|
__u32 data[8];
|
|
|
|
|
} inet_prefix;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This function is to open the netlink socket as the name suggests.
|
|
|
|
|
int netlink_open(struct rtnl_handle* rth) {
|
|
|
|
|
void 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;
|
|
|
|
|
}
|
|
|
|
|
if (rth->fd < 0) throw std::string("cannot open netlink socket");
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) throw std::string("cannot bind netlink socket");
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
if (getsockname(rth->fd, (struct sockaddr*)&rth->local, (socklen_t*) &addr_len) < 0) throw std::string("cannot getsockname");
|
|
|
|
|
if (addr_len != sizeof(rth->local)) throw std::string("wrong address lenght").append(std::to_string(addr_len));
|
|
|
|
|
if (rth->local.nl_family != AF_NETLINK) throw std::string("wrong address family").append(std::to_string(rth->local.nl_family));
|
|
|
|
|
|
|
|
|
|
rth->seq = time(NULL);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This function does the actual reading and writing to the netlink socket
|
|
|
|
@ -352,12 +332,10 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, unsigned
|
|
|
|
|
nladdr.nl_pid = peer;
|
|
|
|
|
nladdr.nl_groups = groups;
|
|
|
|
|
n->nlmsg_seq = ++rtnl->seq;
|
|
|
|
|
if (answer == NULL)
|
|
|
|
|
n->nlmsg_flags |= NLM_F_ACK;
|
|
|
|
|
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;
|
|
|
|
|
return sendmsg(rtnl->fd, &msg, 0);
|
|
|
|
|
// if (status < 0) return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is the utility function for adding the parameters to the packet.
|
|
|
|
@ -375,101 +353,30 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) {
|
|
|
|
|
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;;
|
|
|
|
|
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()) {
|
|
|
|
|
struct rtnl_handle * rth;
|
|
|
|
|
rth = (rtnl_handle*)malloc(sizeof(rtnl_handle));
|
|
|
|
|
netlink_open(rth);
|
|
|
|
|
int err;
|
|
|
|
|
inet_prefix lcl;
|
|
|
|
|
|
|
|
|
|
// structure of the netlink packet.
|
|
|
|
|
struct {
|
|
|
|
|
struct nlmsghdr n;
|
|
|
|
|
struct ifaddrmsg ifa;
|
|
|
|
|
char buf[1024];
|
|
|
|
|
struct nlmsghdr n;
|
|
|
|
|
struct ifaddrmsg ifa;
|
|
|
|
|
char buf[1024];
|
|
|
|
|
} req;
|
|
|
|
|
|
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
@ -480,14 +387,18 @@ void IpManeger::SetInInterface(std::string interfaceName) {
|
|
|
|
|
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 ;
|
|
|
|
|
req.ifa.ifa_scope = 0;
|
|
|
|
|
|
|
|
|
|
memset(&lcl, 0, sizeof(lcl));
|
|
|
|
|
lcl.family = req.ifa.ifa_family;
|
|
|
|
|
lcl.bytelen = (req.ifa.ifa_family == AF_INET) ? 4 : 16;
|
|
|
|
|
lcl.bitlen = (req.ifa.ifa_family == AF_INET) ? 32 : 128;
|
|
|
|
|
|
|
|
|
|
if (inet_pton(req.ifa.ifa_family, ip.Address.c_str(), &lcl.data) <= 0) throw std::string("Invalid IP address: ").append(ip.Address);
|
|
|
|
|
|
|
|
|
|
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!");
|
|
|
|
|
addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen);
|
|
|
|
|
if ((err = rtnl_talk(rth, &req.n, 0, 0, NULL)) < 0) throw std::string("Cannot set interface IP, code: ").append(std::to_string(err));
|
|
|
|
|
}
|
|
|
|
|
}
|