working commit

This commit is contained in:
Олег Бородин
2026-05-07 11:24:50 +02:00
parent 9540ac05d4
commit a5d78c09a6
18 changed files with 2192 additions and 3226 deletions
+3 -2
View File
@@ -105,7 +105,7 @@ CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(sbindir)" am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS) PROGRAMS = $(sbin_PROGRAMS)
am__objects_1 = uxlogger.$(OBJEXT) msgheader.$(OBJEXT) \ am__objects_1 = uxlogger.$(OBJEXT) msgheader.$(OBJEXT) \
interface.$(OBJEXT) uxcontrol.pb.$(OBJEXT) interface.$(OBJEXT) iprouter.$(OBJEXT) uxcontrol.pb.$(OBJEXT)
am_helmetcli_OBJECTS = helmetcli.$(OBJEXT) uxclient.$(OBJEXT) \ am_helmetcli_OBJECTS = helmetcli.$(OBJEXT) uxclient.$(OBJEXT) \
$(am__objects_1) $(am__objects_1)
helmetcli_OBJECTS = $(am_helmetcli_OBJECTS) helmetcli_OBJECTS = $(am_helmetcli_OBJECTS)
@@ -219,7 +219,7 @@ CSCOPE = cscope
CTAGS = ctags CTAGS = ctags
CXX = g++ CXX = g++
CXXDEPMODE = depmode=none CXXDEPMODE = depmode=none
CXXFLAGS = -std=c++23 -Wall -I. -pthread -D_GNU_SOURCE=1 -MMD -MP CXXFLAGS = -O1 -std=c++23 -Wall -I. -pthread -D_GNU_SOURCE=1 -MMD -MP
CYGPATH_W = echo CYGPATH_W = echo
DEFS = -DHAVE_CONFIG_H DEFS = -DHAVE_CONFIG_H
DEPDIR = .deps DEPDIR = .deps
@@ -314,6 +314,7 @@ helmet_SOURCES = \
uxlogger.cpp uxlogger.hpp \ uxlogger.cpp uxlogger.hpp \
msgheader.cpp msgheader.hpp \ msgheader.cpp msgheader.hpp \
interface.cpp interface.hpp \ interface.cpp interface.hpp \
iprouter.cpp iprouter.hpp \
uxcontrol.pb.cc uxcontrol.pb.h uxcontrol.pb.cc uxcontrol.pb.h
ASTYLE_OPTS = --indent=spaces=8 --style=java ASTYLE_OPTS = --indent=spaces=8 --style=java
+2 -1
View File
@@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo subdir-objects AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo subdir-objects
CXXFLAGS = -std=c++23 -Wall -I. -pthread -D_GNU_SOURCE=1 -MMD -MP CXXFLAGS = -O1 -std=c++23 -Wall -I. -pthread -D_GNU_SOURCE=1 -MMD -MP
LDFLAGS = -pthread LDFLAGS = -pthread
LIBS = -Wl,--as-need -lprotobuf LIBS = -Wl,--as-need -lprotobuf
@@ -20,6 +20,7 @@ helmet_SOURCES = \
uxlogger.cpp uxlogger.hpp \ uxlogger.cpp uxlogger.hpp \
msgheader.cpp msgheader.hpp \ msgheader.cpp msgheader.hpp \
interface.cpp interface.hpp \ interface.cpp interface.hpp \
iprouter.cpp iprouter.hpp \
uxcontrol.pb.cc uxcontrol.pb.h uxcontrol.pb.cc uxcontrol.pb.h
ASTYLE_OPTS = --indent=spaces=8 --style=java ASTYLE_OPTS = --indent=spaces=8 --style=java
+3 -2
View File
@@ -105,7 +105,7 @@ CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(sbindir)" am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS) PROGRAMS = $(sbin_PROGRAMS)
am__objects_1 = uxlogger.$(OBJEXT) msgheader.$(OBJEXT) \ am__objects_1 = uxlogger.$(OBJEXT) msgheader.$(OBJEXT) \
interface.$(OBJEXT) uxcontrol.pb.$(OBJEXT) interface.$(OBJEXT) iprouter.$(OBJEXT) uxcontrol.pb.$(OBJEXT)
am_helmetcli_OBJECTS = helmetcli.$(OBJEXT) uxclient.$(OBJEXT) \ am_helmetcli_OBJECTS = helmetcli.$(OBJEXT) uxclient.$(OBJEXT) \
$(am__objects_1) $(am__objects_1)
helmetcli_OBJECTS = $(am_helmetcli_OBJECTS) helmetcli_OBJECTS = $(am_helmetcli_OBJECTS)
@@ -219,7 +219,7 @@ CSCOPE = @CSCOPE@
CTAGS = @CTAGS@ CTAGS = @CTAGS@
CXX = @CXX@ CXX = @CXX@
CXXDEPMODE = @CXXDEPMODE@ CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = -std=c++23 -Wall -I. -pthread -D_GNU_SOURCE=1 -MMD -MP CXXFLAGS = -O1 -std=c++23 -Wall -I. -pthread -D_GNU_SOURCE=1 -MMD -MP
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@@ -314,6 +314,7 @@ helmet_SOURCES = \
uxlogger.cpp uxlogger.hpp \ uxlogger.cpp uxlogger.hpp \
msgheader.cpp msgheader.hpp \ msgheader.cpp msgheader.hpp \
interface.cpp interface.hpp \ interface.cpp interface.hpp \
iprouter.cpp iprouter.hpp \
uxcontrol.pb.cc uxcontrol.pb.h uxcontrol.pb.cc uxcontrol.pb.h
ASTYLE_OPTS = --indent=spaces=8 --style=java ASTYLE_OPTS = --indent=spaces=8 --style=java
+36 -122
View File
@@ -32,10 +32,11 @@ std::expected<void, std::string> Interface::Create(const std::string name) {
std::string error = std::strerror(errnocopy); std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error); return std::unexpected("Create interface error: " + error);
} }
struct ifreq ifr; struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI; ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1); strncpy(ifr.ifr_name, name.data(), IFNAMSIZ - 1);
if (ioctl(tunfd, TUNSETIFF, (void*)(&ifr)) < 0) { if (ioctl(tunfd, TUNSETIFF, (void*)(&ifr)) < 0) {
close(tunfd); close(tunfd);
int errnocopy = errno; int errnocopy = errno;
@@ -43,7 +44,8 @@ std::expected<void, std::string> Interface::Create(const std::string name) {
return std::unexpected("Create interface error: " + error); return std::unexpected("Create interface error: " + error);
} }
ifname = ifr.ifr_name; ifname = ifr.ifr_name;
#if 0
#if DEFINE_TUNPERSIST
if (ioctl(tunfd, TUNSETPERSIST, 0) < 0) { if (ioctl(tunfd, TUNSETPERSIST, 0) < 0) {
close(tunfd); close(tunfd);
int errnocopy = errno; int errnocopy = errno;
@@ -61,7 +63,7 @@ std::expected<void, std::string> Interface::Create(const std::string name) {
std::string error = std::strerror(errnocopy); std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error); return std::unexpected("Get MTU error: " + error);
} }
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1); strncpy(ifr.ifr_name, ifname.data(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0) { if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0) {
close(tunfd); close(tunfd);
close(sockfd); close(sockfd);
@@ -83,7 +85,7 @@ std::expected<void, std::string> Interface::SetMTU(int ifmtu) {
} }
struct ifreq ifr; struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1); strncpy(ifr.ifr_name, ifname.data(), IFNAMSIZ - 1);
ifr.ifr_mtu = ifmtu; ifr.ifr_mtu = ifmtu;
if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) { if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
close(sockfd); close(sockfd);
@@ -104,7 +106,7 @@ std::expected<int, std::string> Interface::GetMTU(void) {
std::string error = std::strerror(errnocopy); std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error); return std::unexpected("Get MTU error: " + error);
} }
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1); strncpy(ifr.ifr_name, ifname.data(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0) { if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0) {
close(sockfd); close(sockfd);
int errnocopy = errno; int errnocopy = errno;
@@ -125,7 +127,7 @@ std::expected<std::string, std::string> Interface::GetIP4Address(void) {
return std::unexpected("Get MTU error: " + error); return std::unexpected("Get MTU error: " + error);
} }
ifr.ifr_addr.sa_family = AF_INET; ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1); strncpy(ifr.ifr_name, ifname.data(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) { if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
close(sockfd); close(sockfd);
@@ -143,23 +145,24 @@ std::expected<std::string, std::string> Interface::GetIP4Address(void) {
std::expected<void, std::string> Interface::SetIP4Address(std::string ipaddr) { std::expected<void, std::string> Interface::SetIP4Address(std::string ipaddr) {
struct ifreq ifr; struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.data(), IFNAMSIZ - 1);
struct sockaddr_in* addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
if (inet_pton(AF_INET, ipaddr.data(), &addr->sin_addr) <= 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set address error: " + error);
}
int sockfd = 0; int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno; int errnocopy = errno;
std::string error = std::strerror(errnocopy); std::string error = std::strerror(errnocopy);
return std::unexpected("Set address error: " + error); return std::unexpected("Set address error: " + error);
} }
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
struct sockaddr_in* addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
if (inet_pton(AF_INET, ipaddr.c_str(), &addr->sin_addr) <= 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set address error: " + error);
}
if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) { if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
close(sockfd); close(sockfd);
int errnocopy = errno; int errnocopy = errno;
@@ -174,7 +177,8 @@ std::expected<void, std::string> Interface::SetIP4Netmask(int prefix) {
if (prefix < 0 || prefix > 32) { if (prefix < 0 || prefix > 32) {
return std::unexpected("Invalid prefix"); return std::unexpected("Invalid prefix");
} }
uint32_t mask = (prefix == 0) ? 0 : (~0U << (32 - prefix)); //uint32_t mask = (prefix == 0) ? 0 : (~0U << (32 - prefix));
uint32_t mask = (prefix == 0) ? 0 : htonl(~((1U << (32 - prefix)) - 1));
struct in_addr maskaddr; struct in_addr maskaddr;
maskaddr.s_addr = htonl(mask); maskaddr.s_addr = htonl(mask);
@@ -182,28 +186,28 @@ std::expected<void, std::string> Interface::SetIP4Netmask(int prefix) {
if (inet_ntop(AF_INET, &maskaddr, buffer, sizeof(buffer)) == NULL) { if (inet_ntop(AF_INET, &maskaddr, buffer, sizeof(buffer)) == NULL) {
int errnocopy = errno; int errnocopy = errno;
std::string error = std::strerror(errnocopy); std::string error = std::strerror(errnocopy);
return std::unexpected("Set1 netmask error: " + error); return std::unexpected("Set netmask error: " + error);
} }
auto netmask = std::string(buffer); auto netmask = std::string(buffer);
struct ifreq ifr; struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.data(), IFNAMSIZ - 1);
struct sockaddr_in* addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
if (inet_pton(AF_INET, netmask.data(), &addr->sin_addr) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set netmask error: " + error);
}
int sockfd = 0; int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno; int errnocopy = errno;
std::string error = std::strerror(errnocopy); std::string error = std::strerror(errnocopy);
return std::unexpected("Set2 netmask error: " + error); return std::unexpected("Set netmask error: " + error);
}
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
struct sockaddr_in* addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
if (inet_pton(AF_INET, netmask.c_str(), &addr->sin_addr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set3 netmask error: " + error);
} }
if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) { if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
close(sockfd); close(sockfd);
@@ -225,7 +229,7 @@ std::expected<void, std::string> Interface::Up(void) {
struct ifreq ifr; struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1); strncpy(ifr.ifr_name, ifname.data(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
close(sockfd); close(sockfd);
int errnocopy = errno; int errnocopy = errno;
@@ -252,7 +256,7 @@ std::expected<void, std::string> Interface::Down(void) {
} }
struct ifreq ifr; struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1); strncpy(ifr.ifr_name, ifname.data(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
close(sockfd); close(sockfd);
int errnocopy = errno; int errnocopy = errno;
@@ -295,93 +299,3 @@ Interface::~Interface() {
close(tunfd); close(tunfd);
} }
std::expected<void, std::string> Interface::UpN(void) {
int netlinkfd = 0;
if ((netlinkfd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
struct {
struct nlmsghdr header;
struct ifinfomsg content;
} request;
memset(&request, 0, sizeof request);
request.header.nlmsg_len = NLMSG_LENGTH(sizeof request.content);
request.header.nlmsg_flags = NLM_F_REQUEST;
request.header.nlmsg_type = RTM_NEWLINK;
request.content.ifi_index = if_nametoindex(ifname.c_str());
request.content.ifi_flags = IFF_UP;
request.content.ifi_change = 1;
if (send(netlinkfd, &request, request.header.nlmsg_len, 0) < 0) {
close(netlinkfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
close(netlinkfd);
return {};
}
std::expected<void, std::string> Interface::SetIP4AddrMask(const std::string address, const int prefix) {
int netlinkfd = 0;
if ((netlinkfd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
int rc = 0;
struct sockaddr_nl sockaddr;
memset(&sockaddr, 0, sizeof sockaddr);
sockaddr.nl_family = AF_NETLINK;
if ((rc = bind(netlinkfd, (struct sockaddr*) &sockaddr, sizeof sockaddr))< 0) {
close(netlinkfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set interface address error: " + error);
}
struct {
struct nlmsghdr header;
struct ifaddrmsg content;
char attributes_buf[64];
} request;
struct rtattr *request_attr;
size_t attributes_buf_avail = sizeof request.attributes_buf;
memset(&request, 0, sizeof request);
request.header.nlmsg_len = NLMSG_LENGTH(sizeof request.content);
request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_EXCL | NLM_F_CREATE;
request.header.nlmsg_type = RTM_NEWADDR;
request.content.ifa_index = if_nametoindex(ifname.c_str());
request.content.ifa_family = AF_INET;
request.content.ifa_prefixlen = prefix;
/* request.attributes[IFA_LOCAL] = address */
request_attr = IFA_RTA(&request.content);
request_attr->rta_type = IFA_LOCAL;
request_attr->rta_len = RTA_LENGTH(sizeof (struct in_addr));
request.header.nlmsg_len += request_attr->rta_len;
inet_pton(AF_INET, address.c_str(), RTA_DATA(request_attr));
/* request.attributes[IFA_ADDRESS] = address */
request_attr = RTA_NEXT(request_attr, attributes_buf_avail);
request_attr->rta_type = IFA_ADDRESS;
request_attr->rta_len = RTA_LENGTH(sizeof (struct in_addr));
request.header.nlmsg_len += request_attr->rta_len;
inet_pton(AF_INET, address.c_str(), RTA_DATA(request_attr));
if (send(netlinkfd, &request, request.header.nlmsg_len, 0) < 0) {
close(netlinkfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set interface address error: " + error);
}
close(netlinkfd);
return {};
}
-3
View File
@@ -10,7 +10,6 @@ private:
public: public:
std::expected<void, std::string> Create(const std::string name); std::expected<void, std::string> Create(const std::string name);
std::string Name(void); std::string Name(void);
//int TunDescr(void);
int MTU(); int MTU();
std::expected<void, std::string> SetMTU(int mtu); std::expected<void, std::string> SetMTU(int mtu);
@@ -21,8 +20,6 @@ public:
std::expected<void, std::string> Up(void); std::expected<void, std::string> Up(void);
std::expected<void, std::string> Down(void); std::expected<void, std::string> Down(void);
std::expected<void, std::string> UpN(void);
std::expected<void, std::string> SetIP4AddrMask(const std::string address, const int prefix);
std::expected<std::string, std::string> Read(void); std::expected<std::string, std::string> Read(void);
+93
View File
@@ -0,0 +1,93 @@
extern "C" {
#include <arpa/inet.h>
#include <linux/rtnetlink.h>
#include <net/route.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
}
#define BUFSIZE 8192
#include <expected>
#include <vector>
#include <format>
#include <cstring>
#include <iprouter.hpp>
std::expected<void, std::string> Router::AddRoute(std::string address, uint64_t prefix, std::string gateway) {
struct sockaddr_in sa;
if (inet_pton(AF_INET, address.data(), &(sa.sin_addr)) == 1) {
} else {
return std::unexpected(std::format("Incorrect address {}", address));
}
struct rtentry rt;
memset(&rt, 0, sizeof(rt));
struct sockaddr_in *sin;
sin = (struct sockaddr_in*)&rt.rt_dst;
sin->sin_family = AF_INET;
if (inet_pton(AF_INET, address.data(), &sin->sin_addr) != 1) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Incorrect address {}, error: {}", address, error));
};
sin = (struct sockaddr_in*) &rt.rt_gateway;
sin->sin_family = AF_INET;
if (inet_pton(AF_INET, gateway.data(), &sin->sin_addr) != 1) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Incorrect address {}, error: {}", gateway, error));
};
char buffer[INET_ADDRSTRLEN];
uint32_t mask = (prefix == 0) ? 0 : htonl(~((1U << (32 - prefix)) - 1));
//uint32_t mask = (prefix == 0) ? 0 : (~0U << (32 - prefix));
struct in_addr addr;
addr.s_addr = mask;
const char *dottedmask;
if ((dottedmask = inet_ntop(AF_INET, &addr, buffer, INET_ADDRSTRLEN)) == NULL) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Incorrect prefix {}, error: {}", prefix, error));
};
sin = (struct sockaddr_in*) &rt.rt_genmask;
sin->sin_family = AF_INET;
if (inet_pton(AF_INET, dottedmask, &sin->sin_addr) != 1) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Incorrect address {}, error: {}", gateway, error));
};
rt.rt_flags = RTF_UP | RTF_GATEWAY;
//rt.rt_dev = std::string("eth0").data();
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Error: {}", error));
}
if (ioctl(sockfd, SIOCADDRT, &rt) < 0) {
close(sockfd);
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Cannot set route, error: {}", error));
}
close(sockfd);
return {};
}
+2 -1
View File
@@ -13,6 +13,7 @@ public:
using Routes = std::vector<Route>; using Routes = std::vector<Route>;
class Router { class Router {
std::expected<Routes, std::string> List(); public:
std::expected<void, std::string> AddRoute(std::string address, uint64_t prefix, std::string gateway);
}; };
+1 -1
View File
@@ -37,7 +37,7 @@ std::expected<void, std::string> MessageHeader::Decode(const std::string rawHead
std::memcpy(&tmp, rawHeader.data(), sizeof(uint32_t)); std::memcpy(&tmp, rawHeader.data(), sizeof(uint32_t));
auto magic = ntohl(tmp); auto magic = ntohl(tmp);
if (magic != msgMagic) { if (magic != msgMagic) {
return std::unexpected("Wrong magic code"); return std::unexpected(std::format("Wrong magic code {:x}", magic));
} }
std::memcpy(&tmp, rawHeader.data() + sizeof(uint32_t), sizeof(uint32_t)); std::memcpy(&tmp, rawHeader.data() + sizeof(uint32_t), sizeof(uint32_t));
pSize = ntohl(tmp); pSize = ntohl(tmp);
+76
View File
@@ -0,0 +1,76 @@
extern "C" {
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
}
#include <cstring>
#include <expected>
#include <string>
#include <resolver.hpp>
Address::Address(std::string iaddress, int ifamily) {
address = iaddress;
family = ifamily;
}
int Address::GetFamily() {
return family;
}
std::string Address::GetAddress() {
return address;
}
std::expected<Address, std::string> Resolver::Resolve(std::string hostname) {
struct sockaddr_in sa;
if (inet_pton(AF_INET, hostname.data(), &(sa.sin_addr)) == 1) {
family = AF_INET;
return Address(hostname, AF_INET);
}
if (inet_pton(AF_INET6, hostname.data(), &(sa.sin_addr)) == 1) {
return Address(hostname, AF_INET6);
}
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
int status = 0;
if ((status = getaddrinfo(hostname.data(), NULL, &hints, &res)) != 0) {
std::string error = gai_strerror(status);
return std::unexpected("Resolve adress error: " + error);
}
struct addrinfo* p;
char ipaddr[INET6_ADDRSTRLEN + 1];
for (p = res; p != NULL; p = p->ai_next) {
if (p->ai_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
void* addr = &(ipv4->sin_addr);
if (inet_ntop(p->ai_family, addr, ipaddr, sizeof(ipaddr)) == NULL) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Cannot conver address: " + error);
}
std::string address(ipaddr);
return Address(address, AF_INET);;
}
}
for (p = res; p != NULL; p = p->ai_next) {
if (p->ai_family == AF_INET6) {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
void* addr = &(ipv6->sin6_addr);
if (inet_ntop(p->ai_family, addr, ipaddr, sizeof(ipaddr)) == NULL) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Cannot conver address: " + error);
}
std::string address(ipaddr);
return Address(address, AF_INET6);
}
}
return std::unexpected("Cannot resolve hostname " + hostname);
}
+20
View File
@@ -0,0 +1,20 @@
#include <expected>
#include <string>
class Address {
private:
int family;
std::string address;
public:
Address(const std::string iaddress, const int ifamily);
int GetFamily();
std::string GetAddress();
};
class Resolver {
private:
int family;
public:
std::expected<Address, std::string> Resolve(const std::string hostname);
};
+2 -7
View File
@@ -80,8 +80,6 @@ void SocketHandler::RecvMessages(void) {
uxlogger.Log(std::format("Read only {} from {} bytes", rsize, msgHeaderSize)); uxlogger.Log(std::format("Read only {} from {} bytes", rsize, msgHeaderSize));
break; break;
} }
uxlogger.Log(std::format("Receive header rsize {}", rsize));
MessageHeader header; MessageHeader header;
auto decodeRes = header.Decode(rawHeader); auto decodeRes = header.Decode(rawHeader);
if (!decodeRes) { if (!decodeRes) {
@@ -89,8 +87,6 @@ void SocketHandler::RecvMessages(void) {
break; break;
} }
auto pSize = header.PacketSize(); auto pSize = header.PacketSize();
uxlogger.Log(std::format("Message size {}", pSize));
if (pSize > 0) { if (pSize > 0) {
std::string rawMessage(pSize, 0); std::string rawMessage(pSize, 0);
if ((rsize = recv(sock, rawMessage.data(), rawMessage.size(), MSG_WAITALL)) < 0) { if ((rsize = recv(sock, rawMessage.data(), rawMessage.size(), MSG_WAITALL)) < 0) {
@@ -99,10 +95,9 @@ void SocketHandler::RecvMessages(void) {
uxlogger.Log(std::format("Read message error: {}", error)); uxlogger.Log(std::format("Read message error: {}", error));
break; break;
} }
uxlogger.Log(std::format("Receive message rsize {}", rsize)); uxcontrol::SimpleMessage msg;
uxcontrol::Message msg;
msg.ParseFromString(rawMessage); msg.ParseFromString(rawMessage);
uxlogger.Log(std::format("Receive message, kind {}", msg.meta().kind())); uxlogger.Log(std::format("Receive message {}", msg.meta().kind()));
} }
} }
done.release(); done.release();
+20 -18
View File
@@ -19,6 +19,7 @@ extern "C" {
#include <uxclient.hpp> #include <uxclient.hpp>
#include <msgheader.hpp> #include <msgheader.hpp>
#include <uxlogger.hpp> #include <uxlogger.hpp>
#include <iprouter.hpp>
#include <uxcontrol.pb.h> #include <uxcontrol.pb.h>
@@ -116,26 +117,13 @@ void UxClient::RecvMessages(void) {
void UxClient::SendMessages(void) { void UxClient::SendMessages(void) {
while (true) { while (true) {
auto readRes = interface.Read(); auto readRes = interface.Read();
if (!readRes) { if (!readRes) {
uxlogger.Log(std::format("Read packet error: {}", readRes.error())); uxlogger.Log(std::format("Read packet error: {}", readRes.error()));
} }
auto packet = readRes.value(); auto packet = readRes.value();
uxlogger.Log(std::format("Read packet size {}", packet.size()));
int wsize = 0; uxcontrol::PacketMessage intPacket;
MessageHeader header(packet.size());
auto rawHeader = header.Encode();
if ((wsize = write(sock, rawHeader.data(), rawHeader.size())) < 0) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
uxlogger.Log(std::format("Write header error: {}", error));
break;
}
uxlogger.Log(std::format("Write header wsize: {}", wsize));
uxcontrol::InternetPacket intPacket;
auto meta = intPacket.mutable_meta(); auto meta = intPacket.mutable_meta();
meta->set_kind("internetPacket"); meta->set_kind("internetPacket");
intPacket.set_payload(packet); intPacket.set_payload(packet);
@@ -143,15 +131,22 @@ void UxClient::SendMessages(void) {
std::string rawMessage; std::string rawMessage;
intPacket.SerializeToString(&rawMessage); intPacket.SerializeToString(&rawMessage);
if ((wsize = write(sock, rawMessage.data(), rawMessage.size())) < 0) { MessageHeader header(rawMessage.size());
auto rawHeader = header.Encode();
int wsize = 0;
if ((wsize = send(sock, rawHeader.data(), rawHeader.size(), 0)) < 0) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
uxlogger.Log(std::format("Write header error: {}", error));
break;
}
if ((wsize = send(sock, rawMessage.data(), rawMessage.size(), 0)) < 0) {
int errnoCopy = errno; int errnoCopy = errno;
std::string error = std::strerror(errnoCopy); std::string error = std::strerror(errnoCopy);
uxlogger.Log(std::format("Write message error: {}", error)); uxlogger.Log(std::format("Write message error: {}", error));
break; break;
} }
uxlogger.Log("Send message"); uxlogger.Log("Send message");
//std::this_thread::sleep_for(std::chrono::seconds(1));
} }
done.release(); done.release();
return; return;
@@ -168,7 +163,7 @@ std::expected<void, std::string> UxClient::Run(void) {
if (!setAddrRes) { if (!setAddrRes) {
return std::unexpected(setAddrRes.error()); return std::unexpected(setAddrRes.error());
} }
auto setMaskRes = interface.SetIP4Netmask(24); auto setMaskRes = interface.SetIP4Netmask(30);
if (!setMaskRes) { if (!setMaskRes) {
return std::unexpected(setMaskRes.error()); return std::unexpected(setMaskRes.error());
} }
@@ -180,6 +175,13 @@ std::expected<void, std::string> UxClient::Run(void) {
if (!createRes) { if (!createRes) {
return std::unexpected(createRes.error()); return std::unexpected(createRes.error());
} }
Router router;
auto addRouteRes = router.AddRoute("1.1.1.2", 32, "10.1.1.2");
if (!addRouteRes) {
return std::unexpected(addRouteRes.error());
}
std::thread sendThr(&UxClient::SendMessages, this); std::thread sendThr(&UxClient::SendMessages, this);
sendThr.detach(); sendThr.detach();
+570 -1379
View File
File diff suppressed because it is too large Load Diff
+801 -1644
View File
File diff suppressed because it is too large Load Diff
+21 -35
View File
@@ -5,49 +5,35 @@ package uxcontrol;
//option cc_generic_services = false; //option cc_generic_services = false;
message MsgMeta { message MetaHeader {
string kind = 1; string kind = 1;
} }
message Message { message SimpleMessage {
MsgMeta meta = 1; MetaHeader meta = 1;
} }
message InternetPacket { message PacketMessage {
MsgMeta meta = 1; MetaHeader meta = 1;
bytes payload = 2; bytes payload = 2;
} }
message HelloMsg { message AddressMessage {
MsgMeta meta = 1; MetaHeader meta = 1;
string message = 2; string address = 2;
} uint64 prefix = 3;
}
message ReqMeta { message RouteMessage {
string kind = 1; MetaHeader meta = 1;
} string address = 2;
uint64 prefix = 3;
message ResMeta { string gateway = 4;
bool error = 1; }
string message = 2;
}
message HelloMessage {
message Request { MetaHeader meta = 1;
ReqMeta meta = 1;
}
message Result {
ResMeta meta = 1;
}
message HelloRequest {
ReqMeta meta = 1;
string message = 2;
}
message HelloResult {
ResMeta meta = 1;
string message = 2; string message = 2;
} }
+391
View File
@@ -0,0 +1,391 @@
extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
}
#include <cstring>
#include <expected>
#include <string>
#include <vector>
#include <span>
#include <iostream>
#include <thread>
#include <chrono>
#include <interface.hpp>
std::expected<void, std::string> Interface::Create(const std::string name) {
if ((tunfd = open("/dev/net/tun", O_RDWR | O_CLOEXEC)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);
if (ioctl(tunfd, TUNSETIFF, (void*)(&ifr)) < 0) {
close(tunfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
ifname = ifr.ifr_name;
#if 0
if (ioctl(tunfd, TUNSETPERSIST, 0) < 0) {
close(tunfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
#endif
//struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
close(tunfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0) {
close(tunfd);
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
close(sockfd);
mtu = ifr.ifr_mtu;
return {};
}
std::expected<void, std::string> Interface::SetMTU(int ifmtu) {
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set MTU error: " + error);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
ifr.ifr_mtu = ifmtu;
if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set MTU error: " + error);
}
close(sockfd);
return {};
}
std::expected<int, std::string> Interface::GetMTU(void) {
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
close(sockfd);
return ifr.ifr_mtu;
}
std::expected<std::string, std::string> Interface::GetIP4Address(void) {
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Get MTU error: " + error);
}
close(sockfd);
auto sinaddr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
std::string addr = inet_ntoa(sinaddr);
return addr;
}
std::expected<void, std::string> Interface::SetIP4Address(std::string ipaddr) {
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set address error: " + error);
}
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
struct sockaddr_in* addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
if (inet_pton(AF_INET, ipaddr.c_str(), &addr->sin_addr) <= 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set address error: " + error);
}
if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set address error: " + error);
}
close(sockfd);
return {};
}
std::expected<void, std::string> Interface::SetIP4Netmask(int prefix) {
if (prefix < 0 || prefix > 32) {
return std::unexpected("Invalid prefix");
}
uint32_t mask = (prefix == 0) ? 0 : (~0U << (32 - prefix));
//htonl(~((1U << (32 - prefix)) - 1));
//struct in_addr addr;
//addr.s_addr = mask;
struct in_addr maskaddr;
maskaddr.s_addr = htonl(mask);
char buffer[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &maskaddr, buffer, sizeof(buffer)) == NULL) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set1 netmask error: " + error);
}
auto netmask = std::string(buffer);
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set2 netmask error: " + error);
}
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
struct sockaddr_in* addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
if (inet_pton(AF_INET, netmask.c_str(), &addr->sin_addr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set3 netmask error: " + error);
}
if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set4 netmask error: " + error);
}
close(sockfd);
return {};
}
std::expected<void, std::string> Interface::Up(void) {
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
close(sockfd);
return {};
}
std::expected<void, std::string> Interface::Down(void) {
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
close(sockfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
close(sockfd);
return {};
}
std::expected<std::string, std::string> Interface::Read() {
char buffer[mtu];
int rsize = 0;
if ((rsize = read(tunfd, buffer, sizeof(buffer))) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Read interface error: " + error);
}
std::string rdata;
rdata.append(buffer, rsize);
return rdata;
}
std::string Interface::Name() {
return ifname;
}
int Interface::MTU() {
return mtu;
}
Interface::~Interface() {
close(tunfd);
}
std::expected<void, std::string> Interface::UpN(void) {
int netlinkfd = 0;
if ((netlinkfd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
struct {
struct nlmsghdr header;
struct ifinfomsg content;
} request;
memset(&request, 0, sizeof request);
request.header.nlmsg_len = NLMSG_LENGTH(sizeof request.content);
request.header.nlmsg_flags = NLM_F_REQUEST;
request.header.nlmsg_type = RTM_NEWLINK;
request.content.ifi_index = if_nametoindex(ifname.c_str());
request.content.ifi_flags = IFF_UP;
request.content.ifi_change = 1;
if (send(netlinkfd, &request, request.header.nlmsg_len, 0) < 0) {
close(netlinkfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Up interface error: " + error);
}
close(netlinkfd);
return {};
}
std::expected<void, std::string> Interface::SetIP4AddrMask(const std::string address, const int prefix) {
int netlinkfd = 0;
if ((netlinkfd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE)) < 0) {
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Create interface error: " + error);
}
int rc = 0;
struct sockaddr_nl sockaddr;
memset(&sockaddr, 0, sizeof sockaddr);
sockaddr.nl_family = AF_NETLINK;
if ((rc = bind(netlinkfd, (struct sockaddr*) &sockaddr, sizeof sockaddr))< 0) {
close(netlinkfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set interface address error: " + error);
}
struct {
struct nlmsghdr header;
struct ifaddrmsg content;
char attributes_buf[64];
} request;
struct rtattr *request_attr;
size_t attributes_buf_avail = sizeof request.attributes_buf;
memset(&request, 0, sizeof request);
request.header.nlmsg_len = NLMSG_LENGTH(sizeof request.content);
request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_EXCL | NLM_F_CREATE;
request.header.nlmsg_type = RTM_NEWADDR;
request.content.ifa_index = if_nametoindex(ifname.c_str());
request.content.ifa_family = AF_INET;
request.content.ifa_prefixlen = prefix;
/* request.attributes[IFA_LOCAL] = address */
request_attr = IFA_RTA(&request.content);
request_attr->rta_type = IFA_LOCAL;
request_attr->rta_len = RTA_LENGTH(sizeof (struct in_addr));
request.header.nlmsg_len += request_attr->rta_len;
inet_pton(AF_INET, address.c_str(), RTA_DATA(request_attr));
/* request.attributes[IFA_ADDRESS] = address */
request_attr = RTA_NEXT(request_attr, attributes_buf_avail);
request_attr->rta_type = IFA_ADDRESS;
request_attr->rta_len = RTA_LENGTH(sizeof (struct in_addr));
request.header.nlmsg_len += request_attr->rta_len;
inet_pton(AF_INET, address.c_str(), RTA_DATA(request_attr));
if (send(netlinkfd, &request, request.header.nlmsg_len, 0) < 0) {
close(netlinkfd);
int errnocopy = errno;
std::string error = std::strerror(errnocopy);
return std::unexpected("Set interface address error: " + error);
}
close(netlinkfd);
return {};
}
+151
View File
@@ -0,0 +1,151 @@
extern "C" {
#include <arpa/inet.h>
#include <linux/rtnetlink.h>
#include <net/route.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
}
#define BUFSIZE 8192
#include <expected>
#include <vector>
#include <format>
#include <cstring>
#include <iprouter.hpp>
std::expected<void, std::string> Router::AddRoute(std::string address, uint64_t prefix, std::string gateway) {
struct sockaddr_in sa;
if (inet_pton(AF_INET, address.data(), &(sa.sin_addr)) == 1) {
} else {
return std::unexpected(std::format("Incorrect address {}", address));
}
struct rtentry rt;
memset(&rt, 0, sizeof(rt));
struct sockaddr_in *sin;
sin = (struct sockaddr_in*)&rt.rt_dst;
sin->sin_family = AF_INET;
if (inet_pton(AF_INET, address.data(), &sin->sin_addr) != 1){
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Incorrect address {}, error: {}", address, error));
};
sin = (struct sockaddr_in*) &rt.rt_gateway;
sin->sin_family = AF_INET;
if (inet_pton(AF_INET, gateway.data(), &sin->sin_addr) != 1) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Incorrect address {}, error: {}", gateway, error));
};
char buffer[INET_ADDRSTRLEN];
uint32_t mask = (prefix == 0) ? 0 : htonl(~((1U << (32 - prefix)) - 1));
//uint32_t mask = (prefix == 0) ? 0 : (~0U << (32 - prefix));
struct in_addr addr;
addr.s_addr = mask;
const char *dottedmask;
if ((dottedmask = inet_ntop(AF_INET, &addr, buffer, INET_ADDRSTRLEN)) == NULL) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Incorrect prefix {}, error: {}", prefix, error));
};
sin = (struct sockaddr_in*) &rt.rt_genmask;
sin->sin_family = AF_INET;
if (inet_pton(AF_INET, dottedmask, &sin->sin_addr) != 1) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Incorrect address {}, error: {}", gateway, error));
};
rt.rt_flags = RTF_UP | RTF_GATEWAY;
//rt.rt_dev = std::string("eth0").data();
int sockfd = 0;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Error: {}", error));
}
if (ioctl(sockfd, SIOCADDRT, &rt) < 0) {
close(sockfd);
int errnoCopy = errno;
std::string error = std::strerror(errnoCopy);
return std::unexpected(std::format("Cannot set route, error: {}", error));
}
close(sockfd);
return {};
}
std::expected<Routes, std::string> Router::List(void) {
std::vector<Route> routes;
struct {
struct nlmsghdr n;
struct rtmsg r;
} req;
std::string buffer(1024 * 10, 0);
struct nlmsghdr *nlh;
int sock, len;
if ((sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
return std::unexpected("Create netlink socket error");
}
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
req.n.nlmsg_type = RTM_GETROUTE;
req.r.rtm_family = AF_INET;
send(sock, &req, req.n.nlmsg_len, 0);
while ((len = recv(sock, buffer.data(), buffer.size(), 0)) > 0) {
nlh = (struct nlmsghdr *)buffer.data();
while (NLMSG_OK(nlh, len)) {
if (nlh->nlmsg_type == NLMSG_DONE) {
return {};
};
struct rtmsg *route = (struct rtmsg *)NLMSG_DATA(nlh);
struct rtattr *rta = (struct rtattr *)RTM_RTA(route);
int len = RTM_PAYLOAD(nlh);
char dest_ip[INET_ADDRSTRLEN] = "0.0.0.0";
char gw_ip[INET_ADDRSTRLEN] = "0.0.0.0";
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
switch (rta->rta_type) {
case RTA_DST:
inet_ntop(AF_INET, RTA_DATA(rta), dest_ip, sizeof(dest_ip));
break;
case RTA_GATEWAY:
inet_ntop(AF_INET, RTA_DATA(rta), gw_ip, sizeof(gw_ip));
break;
case RTA_OIF:
int if_idx = *(int *)RTA_DATA(rta);
printf("Interface Index: %d ", if_idx);
break;
}
}
printf("Found route: dest %s / %d, gw %s\n", dest_ip, route->rtm_dst_len, gw_ip);
nlh = NLMSG_NEXT(nlh, len);
}
}
close(sock);
return routes;
}
-11
View File
@@ -1,11 +0,0 @@
#include <expected>
#include <vector>
#include <iprouter.hpp>
std::expected<Routes, std::string> Router::List() {
std::vector<Route> routes;
return routes;
}