diff --git a/Makefile.am b/Makefile.am index 74c1110..7d68f45 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,7 @@ helmetsrv_SOURCES = helmetsrv.cpp \ helmetcli_SOURCES = helmetcli.cpp \ uxclient.cpp uxclient.hpp \ + cliconfig.cpp cliconfig.hpp \ $(helmet_SOURCES) helmet_SOURCES = \ diff --git a/Makefile.in b/Makefile.in index 662a1d9..372f587 100644 --- a/Makefile.in +++ b/Makefile.in @@ -108,7 +108,7 @@ am__objects_1 = uxlogger.$(OBJEXT) msgheader.$(OBJEXT) \ interface.$(OBJEXT) iprouter.$(OBJEXT) stringaux.$(OBJEXT) \ networkaux.$(OBJEXT) uxcontrol.pb.$(OBJEXT) am_helmetcli_OBJECTS = helmetcli.$(OBJEXT) uxclient.$(OBJEXT) \ - $(am__objects_1) + cliconfig.$(OBJEXT) $(am__objects_1) helmetcli_OBJECTS = $(am_helmetcli_OBJECTS) helmetcli_LDADD = $(LDADD) am_helmetsrv_OBJECTS = helmetsrv.$(OBJEXT) tservice.$(OBJEXT) \ @@ -315,6 +315,7 @@ helmetsrv_SOURCES = helmetsrv.cpp \ helmetcli_SOURCES = helmetcli.cpp \ uxclient.cpp uxclient.hpp \ + cliconfig.cpp cliconfig.hpp \ $(helmet_SOURCES) helmet_SOURCES = \ diff --git a/cliconfig.cpp b/cliconfig.cpp new file mode 100644 index 0000000..159d6c5 --- /dev/null +++ b/cliconfig.cpp @@ -0,0 +1,90 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +int ClientConfig::Servport(void) { + return servport; +} + +std::string ClientConfig::Servaddr(void) { + return servaddr; +} + +std::vector ClientConfig::Localnets(void) { + return localnets; +} + +std::expected ClientConfig::Read(std::string filename) { + std::ifstream file; + file.open(filename); + if (file.fail()) { + auto state = file.rdstate(); + if (state & std::ios_base::badbit) { + return std::unexpected("Read/writing error on i/o operation"); + } else if (state & std::ios_base::failbit) { + return std::unexpected("Logical error on i/o operation"); + } + } + + std::string line; + while (std::getline(file, line)) { + auto tokens = split(line, "#;"); + auto keyval = trim(tokens[0]); + if (keyval.size() == 0) continue; + tokens = split(keyval, "="); + if (tokens.size() < 2) continue; + auto key = trim(tokens[0]); + auto val = trim(tokens[1]); + kvmap[key] = val; + if (key == "localnet") { + localnets.push_back(val); + } else if (key == "servaddr") { + servaddr = val; + } else if (key == "servport") { + auto convRes = strtoint(val); + if (!convRes) { + auto msg = std::format("servport: {}", convRes.error()); + return std::unexpected(msg); + } + servport = convRes.value(); + } + } + file.close(); + return {}; +} + +std::expected ClientConfig::Validate(void) { + if (servport == 0) { + return std::unexpected("Zero server port"); + } + if (servaddr.size() == 0) { + return std::unexpected("Zero server address"); + } + + for (const auto& val : localnets) { + auto netprefixRes = netprefix(val); + if (!netprefixRes) { + return std::unexpected("Incorrect local network " + val + ":" + netprefixRes.error()); + } + auto networkRes = network(val); + if (!networkRes) { + return std::unexpected("Incorrect local network " + val + ":" + networkRes.error()); + } + } + return {}; +} diff --git a/cliconfig.hpp b/cliconfig.hpp new file mode 100644 index 0000000..02ef7c5 --- /dev/null +++ b/cliconfig.hpp @@ -0,0 +1,27 @@ + +#ifndef SRVCONFIG_HPP +#define SRVCONFIG_HPP + +#include +#include +#include +#include + +class ClientConfig { +private: + std::map kvmap; + std::vector localnets; + int servport; + std::string servaddr; +public: + std::expected Read(std::string filename); + int Listenport(void); + std::string Tunnelnet(void); + std::vector Localnets(void); + std::expected Validate(void); + int Servport(void); + std::string Servaddr(void); + +}; + +#endif diff --git a/helmetcli.conf b/helmetcli.conf new file mode 100644 index 0000000..b98c4bb --- /dev/null +++ b/helmetcli.conf @@ -0,0 +1,3 @@ +servport = 1025; +serveraddr = 127.0.0.1; +localnet = 10.11.12.0/24; diff --git a/helmetcli.cpp b/helmetcli.cpp index f086589..9fef9e7 100644 --- a/helmetcli.cpp +++ b/helmetcli.cpp @@ -5,19 +5,42 @@ #include #include +#include + +#include + +std::expected Run(void) { + ClientConfig config; + std::string confdir(SRV_CONFDIR); + auto readRes = config.Read(confdir + "/" + "helmetcli.conf"); + if (!readRes) { + return std::unexpected("Read config error: " + readRes.error()); + } + auto validateRes = config.Validate(); + if (!validateRes) { + return std::unexpected("Validate config error: " + validateRes.error()); + } + auto servaddr = config.Servaddr(); + auto servport = config.Servport(); + auto localnets = config.Localnets(); -int main(int argc, char** argv) { UxClient client; - auto connectRes = client.Connect("127.0.0.1", 1025); + auto connectRes = client.Connect(servaddr, servport); if (!connectRes) { - uxlogger.Error(connectRes.error()); - return 1; + return std::unexpected(connectRes.error()); } auto runRes = client.Run(); + if (!runRes) { + return std::unexpected(runRes.error()); + } + return {}; +} + +int main(int argc, char** argv) { + auto runRes = Run(); if (!runRes) { uxlogger.Error(runRes.error()); return 1; } - } diff --git a/sockhand.cpp b/sockhand.cpp index 1315d91..6593446 100644 --- a/sockhand.cpp +++ b/sockhand.cpp @@ -16,11 +16,13 @@ extern "C" { #include #include #include +#include #include void SocketHandler::Handle(int newsock, std::string laddr, std::string raddr, std::vector routes) { sock = newsock; + tunAddress = raddr; auto interfaceName = std::format("uxsrv{}", sock); auto createRes = interface.Create(interfaceName); if (!createRes) { @@ -213,6 +215,27 @@ void SocketHandler::RecvMessages(void) { auto error = writeRes.error(); uxlogger.Error(std::format("Write packet error: {}", error)); } + } else if (kind == localRouteMsg) { + uxcontrol::RouteMessage routeMessage; + routeMessage.ParseFromString(rawMessage); + auto network = routeMessage.address(); + auto prefix = routeMessage.prefix(); + auto networkRes = nethost(network, prefix, 0); + if (!networkRes) { + uxlogger.Error(networkRes.error()); + break; + } + network = networkRes.value(); + uxlogger.Info(std::format("Received route {}/{} gw {}", network, prefix, tunAddress)); + if (tunAddress != "") { + Router router; + auto addRouteRes = router.AddRoute(network, prefix, tunAddress, interface.Name()); + if (!addRouteRes) { + uxlogger.Error(addRouteRes.error()); + } else { + uxlogger.Warning(std::format("Add route {}/{}", network, prefix)); + } + } } else { uxlogger.Warning("Received unknown kind of message"); } diff --git a/sockhand.hpp b/sockhand.hpp index d05b337..a74b2a6 100644 --- a/sockhand.hpp +++ b/sockhand.hpp @@ -15,6 +15,7 @@ private: std::mutex intMtx; std::binary_semaphore done{0}; Interface interface; + std::string tunAddress; public: void Handle(int newsock, std::string laddr, std::string raddr, std::vector routes); void RecvMessages(void); diff --git a/uxclient.cpp b/uxclient.cpp index 0c8102d..71ff376 100644 --- a/uxclient.cpp +++ b/uxclient.cpp @@ -119,7 +119,16 @@ void UxClient::RecvMessages(void) { auto kind = metaPart.kind(); uxlogger.Debug(std::format("Received message kind: {}", kind)); - if (kind == tunAddressMsg) { + if (kind == internetPkgMsg) { + uxcontrol::PacketMessage packetMessage; + packetMessage.ParseFromString(rawMessage); + auto payload = packetMessage.payload(); + auto writeRes = interface.Write(payload); + if (!writeRes) { + auto error = writeRes.error(); + uxlogger.Error(std::format("Write packet error: {}", error)); + } + } else if (kind == tunAddressMsg) { uxcontrol::AddressMessage addrMessage; addrMessage.ParseFromString(rawMessage); uxlogger.Debug(std::format("Receive address {}", addrMessage.address())); @@ -133,15 +142,6 @@ void UxClient::RecvMessages(void) { uxlogger.Error(setMaskRes.error()); } tunAddress = addrMessage.address(); - } else if (kind == internetPkgMsg) { - uxcontrol::PacketMessage packetMessage; - packetMessage.ParseFromString(rawMessage); - auto payload = packetMessage.payload(); - auto writeRes = interface.Write(payload); - if (!writeRes) { - auto error = writeRes.error(); - uxlogger.Error(std::format("Write packet error: {}", error)); - } } else if (kind == localRouteMsg) { uxcontrol::RouteMessage routeMessage; routeMessage.ParseFromString(rawMessage);