blob: 277dc405002742f87822f08fda768f229b0c5161 [file] [log] [blame]
Václav Kubernátd386aba2021-01-19 10:03:28 +01001#include <boost/process.hpp>
2#include <docopt.h>
3#include <spdlog/sinks/ansicolor_sink.h>
4#include <spdlog/spdlog.h>
5#include <sysrepo-cpp/Session.hpp>
6#include <unistd.h>
7#include "VELIA_VERSION.h"
8#include "firewall/Firewall.h"
9#include "utils/exceptions.h"
Václav Kubernát6d9357e2021-01-28 15:38:24 +010010#include "utils/exec.h"
Václav Kubernátd386aba2021-01-19 10:03:28 +010011#include "utils/journal.h"
12#include "utils/log-init.h"
13#include "utils/waitUntilSignalled.h"
14
15/** @short Extract log level from a CLI option */
16spdlog::level::level_enum parseLogLevel(const std::string& name, const docopt::value& option)
17{
18 long x;
19 try {
20 x = option.asLong();
21 } catch (std::invalid_argument&) {
22 throw std::runtime_error(name + " log level: expecting integer");
23 }
24 static_assert(spdlog::level::trace < spdlog::level::off, "spdlog::level levels have changed");
25 static_assert(spdlog::level::off == 6, "spdlog::level levels have changed");
26 if (x < 0 || x > 5)
27 throw std::runtime_error(name + " log level invalid or out-of-range");
28
29 return static_cast<spdlog::level::level_enum>(5 - x);
30}
31
32static const char usage[] =
33 R"(Bridge between sysrepo and nftables.
34
35Usage:
36 veliad-firewall
37 [--sysrepo-log-level=<Level>]
38 [--firewall-log-level=<Level>]
39 veliad-firewall (-h | --help)
40 veliad-firewall --version
41
42Options:
43 -h --help Show this screen.
44 --version Show version.
45 --firewall-log-level=<N> Log level for the firewall [default: 3]
46 --sysrepo-log-level=<N> Log level for the sysrepo library [default: 3]
47)";
48
49int main(int argc, char* argv[])
50{
51 std::shared_ptr<spdlog::sinks::sink> loggingSink;
52 if (velia::utils::isJournaldActive()) {
53 loggingSink = velia::utils::create_journald_sink();
54 } else {
55 loggingSink = std::make_shared<spdlog::sinks::ansicolor_stderr_sink_mt>();
56 }
57
Tomáš Peckac50ec9e2021-01-27 12:22:42 +010058 auto args = docopt::docopt(usage, {argv + 1, argv + argc}, true, "veliad-firewall " VELIA_VERSION, true);
Václav Kubernátd386aba2021-01-19 10:03:28 +010059
60 velia::utils::initLogs(loggingSink);
61 spdlog::set_level(spdlog::level::info);
62
63 try {
64 spdlog::get("firewall")->set_level(parseLogLevel("Firewall logging", args["--firewall-log-level"]));
65 spdlog::get("sysrepo")->set_level(parseLogLevel("Sysrepo library", args["--sysrepo-log-level"]));
66
67 spdlog::get("main")->debug("Opening Sysrepo connection");
68 auto srConn = std::make_shared<sysrepo::Connection>();
69 auto srSess = std::make_shared<sysrepo::Session>(srConn);
70 velia::firewall::SysrepoFirewall firewall(srSess, [] (const auto& config) {
71 spdlog::get("firewall")->debug("running nft...");
Václav Kubernát6d9357e2021-01-28 15:38:24 +010072 velia::utils::execAndWait(spdlog::get("firewall"), "nft", {"-f", "-"}, config);
Václav Kubernátd386aba2021-01-19 10:03:28 +010073
Václav Kubernátd386aba2021-01-19 10:03:28 +010074 spdlog::get("firewall")->debug("nft config applied.");
75 });
76
77 waitUntilSignaled();
78
79 spdlog::get("main")->info("Exiting.");
80
81 return 0;
82 } catch (std::exception& e) {
83 velia::utils::fatalException(spdlog::get("main"), e, "main");
84 }
85}