aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makefile6
-rw-r--r--src/main.cpp327
-rw-r--r--src/wg2nd.cpp (renamed from src/wg2sd.cpp)114
-rw-r--r--src/wg2nd.hpp (renamed from src/wg2sd.hpp)12
-rw-r--r--test/wg2nd_test.cpp (renamed from test/wg2sd_test.cpp)10
5 files changed, 367 insertions, 102 deletions
diff --git a/makefile b/makefile
index 1abde0b..d375869 100644
--- a/makefile
+++ b/makefile
@@ -24,7 +24,7 @@ DEBUGFLAGS = -ggdb -O0
LDFLAGS = -largon2
# Object files
-OBJECTS := wg2sd.o
+OBJECTS := wg2nd.o
OBJECTS += main.o
# Source directory
@@ -41,7 +41,7 @@ OBJ_DIR = obj
DEBUG_OBJ_DIR = obj/debug
# Target executable
-CMD = wg2sd
+CMD = wg2nd
# Build rules
all: CXXFLAGS += $(RELEASE_CXXFLAGS)
@@ -62,7 +62,7 @@ $(CMD): $(addprefix $(OBJ_DIR)/, $(OBJECTS))
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
$(CXX) $(CXXFLAGS) -c $< -o $@
-$(TEST_DIR)/%: $(TEST_DIR)/%.cpp $(addprefix $(OBJ_DIR)/, wg2sd.o) | $(OBJ_DIR)
+$(TEST_DIR)/%: $(TEST_DIR)/%.cpp $(addprefix $(OBJ_DIR)/, wg2nd.o) | $(OBJ_DIR)
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
$(OBJ_DIR) $(DEBUG_OBJ_DIR):
diff --git a/src/main.cpp b/src/main.cpp
index 19b5ced..b8c8ec6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,5 +1,14 @@
+#include <iostream>
+#include <string>
+#include <vector>
+#include <filesystem>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include <getopt.h>
+
// =====================================
-// ERROR HANDING - FROM FCUTILS
+// ERROR HANDING - FROM FCUTILS
// =====================================
#include <stdio.h>
@@ -69,35 +78,122 @@ void err(char const * format, ...) {
}
// =============================================
-// COMMAND LINE UTILITY
+// COMMAND LINE UTILITY
// =============================================
+constexpr char const * DEFAULT_OUTPUT_PATH = "/etc/systemd/network/";
-#include "wg2sd.hpp"
+/*
+ * HELP AND USAGE
+ */
-#include <filesystem>
-#include <fstream>
-#include <iostream>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <grp.h>
+void die_usage(const char *prog) {
+ err("Usage: %s { install, generate } [ OPTIONS ] { -h, CONFIG_FILE }", prog);
+ die("Use -h for help");
+}
+
+void print_help(const char *prog) {
+ err("Usage: %s { install, generate } [ OPTIONS ] { -h, CONFIG_FILE }\n", prog);
+ err(" CONFIG_FILE is the complete path to a WireGuard configuration file, used by");
+ err(" `wg-quick`. `wg2nd` will convert the WireGuard configuration to networkd");
+ err(" files.\n");
+ err(" The generated configurations are functionally equivalent to `wg-quick(8)`");
+ err(" with the following exceptions:\n");
+ err(" 1. When unspecified, `wg-quick` determines whether `FwMark` and `Table` are available dynamically,");
+ err(" ensuring that the routing table and `fwmark` are not already in use. `wg2nd` sets");
+ err(" the `fwmark` to a random number (deterministically generated from the interface");
+ err(" name). If more than 500 `fwmarks` are in use, there is a non-negligible chance of a");
+ err(" collision. This would occur when there are more than 500 active WireGuard interfaces.\n");
+ err(" 2. The PreUp, PostUp, PreDown, and PostDown script snippets are ignored.\n");
+ err(" 3. `wg-quick(8)` installs a firewall when a default route is specified (i.e., when `0.0.0.0/0`");
+ err(" or `::/0` are specified in `AllowedIPs`). This is not installed by");
+ err(" default with `wg2nd install`. The equivalent firewall can be generated with");
+ err(" `wg2nd generate -t nft CONFIG_FILE`. Refer to `nft(8)` for details.\n");
+ err(" Actions:");
+ err(" install Generate and install the configuration with restricted permissions");
+ err(" generate Generate specific configuration files and write the results to stdout\n");
+ err(" Options:");
+ err(" -h Print this help");
+ exit(EXIT_SUCCESS);
+}
-[[noreturn]] void die_usage(char const * prog) {
- err("Usage: %s [ -o OUTPUT_PATH ] CONFIG_FILE", prog);
+void die_usage_generate(const char *prog) {
+ err("Usage: %s generate [ -h ] [ -k KEYPATH ] [ -t { network, netdev, keyfile, nft } ] CONFIG_FILE", prog);
die("Use -h for help");
}
-void print_help(char const * prog) {
- err("Usage: %s [ -h | -f | -o OUTPUT_PATH ] CONFIG_FILE", prog);
+void print_help_generate(const char *prog) {
+ err("Usage: %s generate [ -h ] [ -k KEYPATH ] [ -t { network, netdev, keyfile, nft } ] CONFIG_FILE\n", prog);
err("Options:");
- err("-o OUTPUT_PATH\tSet the output path (default is /etc/systemd/network)");
- err("-f \tOutput firewall rules");
- err("-h \tDisplay this help message");
+ err(" -t FILE_TYPE");
+ err(" network Generate a Network Configuration File (see systemd.network(8))");
+ err(" netdev Generate a Virtual Device File (see systemd.netdev(8))");
+ err(" keyfile Print the interface's private key");
+ err(" nft Print the netfilter table `nft(8)` installed by `wg-quick(8)`\n");
+ err(" -k KEYPATH Full path to the keyfile (a path relative to /etc/systemd/network is generated");
+ err(" if unspecified)\n");
+ err(" -h Print this help");
exit(EXIT_SUCCESS);
}
-using namespace wg2sd;
+void die_usage_install(const char *prog) {
+ err("Usage: %s install [ -h ] [ -f FILE_NAME ] [ -k KEYFILE ] [ -o OUTPUT_PATH ] CONFIG_FILE", prog);
+ die("Use -h for help");
+}
+
+void print_help_install(const char *prog) {
+ err("Usage: %s install [ -h ] [ -f FILE_NAME ] [ -o OUTPUT_PATH ] CONFIG_FILE\n", prog);
+ err(" `wg2nd install` translates `wg-quick(8)` configuration into corresponding");
+ err(" `networkd` configuration and installs the resulting files in `OUTPUT_PATH`.\n");
+ err(" `wg2nd install` generates a `netdev`, `network`, and `keyfile` for each");
+ err(" CONFIG_FILE. Links will be installed with a `manual` `ActivationPolicy`.");
+ err(" The interface can be brought up with `networkctl up INTERFACE` and down");
+ err(" with `networkctl down INTERFACE`.\n");
+ err(" `wg-quick(8)` installs a firewall when a default route (i.e., when `0.0.0.0/0`");
+ err(" or `::/0` is specified in `AllowedIPs`). This is not installed by default");
+ err(" with `wg2nd install`. The equivalent firewall can be generated with");
+ err(" `wg2nd generate -t nft CONFIG_FILE`.\n");
+ err("Options:");
+ err(" -o OUTPUT_PATH The installation path (default is /etc/systemd/network)\n");
+ err(" -f FILE_NAME The base name for the installed configuration files. The");
+ err(" networkd-specific configuration suffix will be added");
+ err(" (FILE_NAME.netdev for systemd-netdev(8) files,");
+ err(" FILE_NAME.network for systemd-network(8) files,");
+ err(" and FILE_NAME.keyfile for keyfiles)\n");
+ err(" -k KEYFILE The name of the private keyfile\n");
+ err(" -h Print this help");
+ exit(EXIT_SUCCESS);
+}
+
+
+/*
+ * PARSING
+ */
+
+enum class FileType {
+ NONE = 0,
+ NETWORK,
+ NETDEV,
+ KEYFILE,
+ NFT
+};
+
+
+/*
+ * INTERNAL LOGIC
+ */
+
+#include "wg2nd.hpp"
+
+#include <iostream>
+#include <fstream>
+#include <optional>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <grp.h>
+
+using namespace wg2nd;
void write_systemd_file(SystemdFilespec const & filespec, std::string output_path, bool secure) {
std::string full_path = output_path + "/" + filespec.name;
@@ -142,44 +238,23 @@ void write_systemd_file(SystemdFilespec const & filespec, std::string output_pat
}
}
-int main(int argc, char ** argv) {
- int opt;
- std::filesystem::path output_path = "/etc/systemd/network";
- bool print_firewall_rules = false;
-
- while ((opt = getopt(argc, argv, "o:fh")) != -1) {
- switch (opt) {
- case 'o':
- output_path = optarg;
- break;
- case 'f':
- print_firewall_rules = true;
- break;
- case 'h':
- print_help(argv[0]);
- break;
- default: /* '?' */
- die_usage(argv[0]);
- }
- }
-
- if (optind >= argc) {
- die_usage(argv[0]);
- }
-
- std::filesystem::path config_path = argv[optind];
+SystemdConfig generate_cfg_or_die(
+ std::filesystem::path && config_path,
+ std::filesystem::path const & keyfile_or_output_path,
+ std::optional<std::string> const & filename
+ ) {
std::fstream cfg_stream { config_path };
if(!cfg_stream.is_open()) {
die("Failed to open config file %s", config_path.string().c_str());
}
- std::string interface_name = interface_name_from_filename(config_path);
-
SystemdConfig cfg;
+ std::string interface_name = interface_name_from_filename(config_path);
+
try {
- cfg = wg2sd::wg2sd(interface_name, cfg_stream, output_path);
+ cfg = wg2nd::wg2nd(interface_name, cfg_stream, keyfile_or_output_path, filename);
} catch(ConfigurationException const & cex) {
const ParsingException * pex = dynamic_cast<const ParsingException *>(&cex);
@@ -191,16 +266,25 @@ int main(int argc, char ** argv) {
}
- if(print_firewall_rules) {
- fprintf(stdout, "%s", cfg.firewall.c_str());
+ return cfg;
+}
- return 0;
- }
+
+void wg2nd_install_internal(std::optional<std::string> && filename, std::string && keyfile_name,
+ std::filesystem::path && output_path, std::filesystem::path && config_path) {
if(!std::filesystem::path(output_path).is_absolute()) {
output_path = std::filesystem::absolute(output_path);
}
+ std::filesystem::path keyfile_or_output_path = output_path;
+
+ if(!keyfile_name.empty()) {
+ keyfile_or_output_path /= keyfile_name;
+ }
+
+ SystemdConfig cfg = generate_cfg_or_die(std::move(config_path), keyfile_or_output_path, std::move(filename));
+
for(std::string const & warning : cfg.warnings) {
err("warning: %s", warning.c_str());
}
@@ -212,6 +296,147 @@ int main(int argc, char ** argv) {
for(SystemdFilespec const & spec : cfg.symmetric_keyfiles) {
write_systemd_file(spec, output_path, true);
}
+}
+
+void wg2nd_generate_internal(FileType type, std::string && config_file,
+ std::optional<std::filesystem::path> && keyfile_path) {
+
+ SystemdConfig cfg = generate_cfg_or_die(
+ std::move(config_file), std::move(keyfile_path.value_or(DEFAULT_OUTPUT_PATH)), {}
+ );
+
+ switch(type) {
+ case FileType::NFT:
+ printf("%s", cfg.firewall.c_str());
+ break;
+ case FileType::NETWORK:
+ printf("%s", cfg.network.contents.c_str());
+ break;
+ case FileType::NETDEV:
+ printf("%s", cfg.netdev.contents.c_str());
+ break;
+ case FileType::KEYFILE:
+ printf("%s", cfg.private_keyfile.contents.c_str());
+ break;
+ default:
+ break;
+ }
+}
+
+
+static int wg2nd_generate(char const * prog, int argc, char **argv) {
+ std::filesystem::path config_path = "";
+
+ FileType type = FileType::NONE;
+ std::optional<std::filesystem::path> keyfile_path = {};
+
+ int opt;
+ while ((opt = getopt(argc, argv, "ht:k:")) != -1) {
+ switch (opt) {
+ case 't':
+ if (strcmp(optarg, "network") == 0) {
+ type = FileType::NETWORK;
+ } else if (strcmp(optarg, "netdev") == 0) {
+ type = FileType::NETDEV;
+ } else if (strcmp(optarg, "keyfile") == 0) {
+ type = FileType::KEYFILE;
+ } else if (strcmp(optarg, "nft") == 0) {
+ type = FileType::NFT;
+ } else {
+ die("Unknown file type: %s", optarg);
+ }
+ break;
+ case 'k':
+ keyfile_path = optarg;
+ break;
+ case 'h':
+ print_help_generate(prog);
+ break;
+ default:
+ die_usage_generate(prog);
+ }
+ }
+
+ if (optind >= argc) {
+ die_usage_generate(prog);
+ }
+
+ config_path = argv[optind];
+
+ wg2nd_generate_internal(type, std::move(config_path), std::move(keyfile_path));
+
+ return 0;
+}
+
+static int wg2nd_install(char const * prog, int argc, char **argv) {
+ std::filesystem::path config_path = "";
+
+ std::optional<std::string> filename = {};
+ std::filesystem::path output_path = DEFAULT_OUTPUT_PATH;
+ std::string keyfile_name = "";
+
+ int opt;
+ while ((opt = getopt(argc, argv, "o:f:k:h")) != -1) {
+ switch (opt) {
+ case 'o': {
+ std::string path = optarg;
+ if(path[path.size() - 1] != '/') {
+ path.push_back('/');
+ }
+ output_path = std::move(path);
+ break;
+ }
+ case 'f':
+ filename = optarg;
+ break;
+ case 'h':
+ print_help_install(prog);
+ break;
+ case 'k':
+ keyfile_name = optarg;
+ break;
+ default:
+ die_usage_install(prog);
+ }
+ }
+
+ if (optind >= argc) {
+ die_usage_install(prog);
+ }
+
+ config_path = argv[optind];
+
+ wg2nd_install_internal(std::move(filename), std::move(keyfile_name), std::move(output_path), std::move(config_path));
+
+ return 0;
+}
+
+// The main function remains the same as before
+
+
+int main(int argc, char **argv) {
+ char const * prog = "wg2nd";
+
+ if(argc > 0) {
+ prog = argv[0];
+ }
+
+ if (argc < 2) {
+ die_usage(prog);
+ }
+
+ std::string action = argv[1];
+
+ if (action == "generate") {
+ return wg2nd_generate(prog, argc - 1, argv + 1);
+ } else if (action == "install") {
+ return wg2nd_install(prog, argc - 1, argv + 1);
+ } else if (action == "-h" || action == "--help") {
+ print_help(prog);
+ } else {
+ err("Unknown action: %s", action.c_str());
+ die_usage(prog);
+ }
return 0;
}
diff --git a/src/wg2sd.cpp b/src/wg2nd.cpp
index 4c39a03..c53df04 100644
--- a/src/wg2sd.cpp
+++ b/src/wg2nd.cpp
@@ -1,4 +1,4 @@
-#include "wg2sd.hpp"
+#include "wg2nd.hpp"
#include <exception>
#include <sstream>
@@ -27,7 +27,7 @@ std::string hashed_keyfile_name(std::string const & priv_key) {
uint8_t hash[HASHLEN];
- argon2i_hash_raw(t_cost, m_cost, parallelism, key, keylen, SALT, sizeof(SALT), hash, HASHLEN);
+ argon2id_hash_raw(t_cost, m_cost, parallelism, key, keylen, SALT, sizeof(SALT), hash, HASHLEN);
constexpr char KEYFILE_EXT[] = ".keyfile";
@@ -47,8 +47,29 @@ std::string hashed_keyfile_name(std::string const & priv_key) {
return std::string { filename } ;
}
+uint32_t deterministic_fwmark(std::string const & interface_name) {
+ constexpr uint8_t const SALT[] = {
+ 0x90, 0x08, 0x82, 0xd7, 0x75, 0x68, 0xf4, 0x8e,
+ 0x90, 0x74, 0x0c, 0x74, 0x0d, 0xf4, 0xfb, 0x91,
+ 0xe5, 0x44, 0x87, 0x7e, 0xce, 0x48, 0xcf, 0x01,
+ };
+
+ uint8_t const * key = reinterpret_cast<uint8_t const *>(interface_name.c_str());
+ uint32_t keylen = interface_name.size();
+
+ uint32_t mark;
+
+ uint8_t t_cost = 2;
+ uint32_t m_cost = 1 << 10;
+ uint32_t parallelism = 1;
+
+ argon2id_hash_raw(t_cost, m_cost, parallelism, key, keylen, SALT, sizeof(SALT), &mark, sizeof(mark));
+
+ return mark;
+}
+
-namespace wg2sd {
+namespace wg2nd {
std::string interface_name_from_filename(std::filesystem::path config_path) {
std::string interface_name = config_path.filename().string();
@@ -219,6 +240,8 @@ namespace wg2sd {
}
cfg.intf.listen_port = port;
+ } else if (key == "MTU") {
+ cfg.intf.mtu = value;
} else if (key == "PreUp") {
cfg.intf.preup = value;
} else if (key == "PostUp") {
@@ -303,7 +326,7 @@ namespace wg2sd {
return cfg;
}
- static void _write_table(std::stringstream & firewall, Config const & cfg, std::vector<std::string_view> addrs, bool ipv4) {
+ static void _write_table(std::stringstream & firewall, Config const & cfg, std::vector<std::string_view> addrs, bool ipv4, uint32_t fwd_table) {
char const * ip = ipv4 ? "ip" : "ip6";
firewall << "table " << ip << " " << cfg.intf.name << " {\n"
@@ -323,13 +346,13 @@ namespace wg2sd {
<< "\n"
<< " chain postmangle {\n"
<< " type filter hook postrouting priority mangle; policy accept;\n"
- << " meta l4proto udp meta mark " << std::hex << cfg.intf.table << std::dec << "ct mark set meta mark;\n"
+ << " meta l4proto udp meta mark 0x" << std::hex << fwd_table << std::dec << " ct mark set meta mark;\n"
<< " }\n"
<< "}\n";
}
- std::string _gen_nftables_firewall(Config const & cfg) {
+ std::string _gen_nftables_firewall(Config const & cfg, uint32_t fwd_table) {
std::stringstream firewall;
std::vector<std::string_view> ipv4_addrs;
@@ -343,39 +366,31 @@ namespace wg2sd {
}
}
- _write_table(firewall, cfg, ipv4_addrs, true);
-
- firewall << "\n";
+ if(ipv4_addrs.size() > 0) {
+ _write_table(firewall, cfg, ipv4_addrs, true, fwd_table);
+ firewall << "\n";
+ }
- _write_table(firewall, cfg, ipv6_addrs, false);
+ if(ipv6_addrs.size() > 0) {
+ _write_table(firewall, cfg, ipv6_addrs, false, fwd_table);
+ }
return firewall.str();
}
- static std::string _gen_netdev_cfg(Config const & cfg, uint32_t fwd_table, std::string const & private_keyfile,
- std::vector<SystemdFilespec> & symmetric_keyfiles, std::string const & output_path) {
+ static std::string _gen_netdev_cfg(Config const & cfg, uint32_t fwd_table, std::filesystem::path const & private_keyfile,
+ std::vector<SystemdFilespec> & symmetric_keyfiles) {
std::stringstream netdev;
- netdev << "# Autogenerated by wg2sd\n";
+ netdev << "# Autogenerated by wg2nd\n";
netdev << "[NetDev]\n";
netdev << "Name = " << cfg.intf.name << "\n";
netdev << "Kind = wireguard\n";
netdev << "Description = " << cfg.intf.name << " - wireguard tunnel\n";
-
- if(!cfg.intf.mtu.empty()) {
- netdev << "MTUBytes = " << cfg.intf.mtu << "\n";
- }
-
netdev << "\n";
netdev << "[WireGuard]\n";
- netdev << "PrivateKeyFile = " << output_path;
-
- if(output_path.back() != '/') {
- netdev << "/";
- }
-
- netdev << private_keyfile << "\n";
+ netdev << "PrivateKeyFile = " << private_keyfile.string() << "\n";
if(cfg.intf.listen_port.has_value()) {
netdev << "ListenPort = " << cfg.intf.listen_port.value() << "\n";
@@ -441,11 +456,18 @@ namespace wg2sd {
static std::string _gen_network_cfg(Config const & cfg, uint32_t fwd_table) {
std::stringstream network;
- network << "# Autogenerated by wg2sd\n";
+ network << "# Autogenerated by wg2nd\n";
network << "[Match]\n";
network << "Name = " << cfg.intf.name << "\n";
network << "\n";
+ network << "[Link]" << "\n";
+ network << "ActivationPolicy = manual\n";
+ if(!cfg.intf.mtu.empty()) {
+ network << "MTUBytes = " << cfg.intf.mtu << "\n";
+ }
+ network << "\n";
+
network << "[Network]\n";
for(std::string const & addr : cfg.intf.addresses) {
network << "Address = " << addr << "\n";
@@ -523,19 +545,21 @@ namespace wg2sd {
return network.str();
}
- static uint32_t _random_table() {
- std::random_device rd;
- std::mt19937 rng { rd() };
+ static uint32_t _deterministic_random_table(std::string const & interface_name) {
uint32_t table = 0;
while(table == 0 or table == MAIN_TABLE or table == LOCAL_TABLE) {
- table = rng() % UINT32_MAX;
+ table = deterministic_fwmark(interface_name);
}
return table;
}
- SystemdConfig gen_systemd_config(Config const & cfg, std::string const & output_path) {
+ SystemdConfig gen_systemd_config(
+ Config const & cfg,
+ std::filesystem::path const & keyfile_or_output_path,
+ std::optional<std::string> const & filename
+ ) {
// If the table is explicitly specified with Table=<number>,
// all routes are added to this table.
@@ -549,11 +573,18 @@ namespace wg2sd {
// table.
//
// If Table=off, no routes are added.
- uint32_t fwd_table = _random_table();
+ uint32_t fwd_table = _deterministic_random_table(cfg.intf.name);
std::vector<SystemdFilespec> symmetric_keyfiles;
- std::string private_keyfile = hashed_keyfile_name(cfg.intf.private_key);
+ std::filesystem::path keyfile_path;
+
+ if(keyfile_or_output_path.has_filename()) {
+ keyfile_path = keyfile_or_output_path;
+ } else {
+ std::string private_keyfile = hashed_keyfile_name(cfg.intf.private_key);
+ keyfile_path = keyfile_or_output_path / private_keyfile;
+ }
std::vector<std::string> warnings;
@@ -572,27 +603,30 @@ if(!cfg.intf.field_.empty()) { \
warnings.push_back("[Interface] section contains a field \"PreUp\" which does not have a systemd-networkd analog");
}
+ std::string const & basename = filename.value_or(cfg.intf.name);
+
return SystemdConfig {
.netdev = {
- .name = cfg.intf.name + ".netdev",
- .contents = _gen_netdev_cfg(cfg, fwd_table, private_keyfile, symmetric_keyfiles, output_path),
+ .name = basename + ".netdev",
+ .contents = _gen_netdev_cfg(cfg, fwd_table, keyfile_path, symmetric_keyfiles),
},
.network = {
- .name = cfg.intf.name + ".network",
+ .name = basename + ".network",
.contents = _gen_network_cfg(cfg, fwd_table)
},
.private_keyfile = {
- .name = private_keyfile,
+ .name = keyfile_path.filename(),
.contents = cfg.intf.private_key + "\n",
},
.symmetric_keyfiles = std::move(symmetric_keyfiles),
.warnings = std::move(warnings),
- .firewall = _gen_nftables_firewall(cfg),
+ .firewall = _gen_nftables_firewall(cfg, fwd_table),
};
}
- SystemdConfig wg2sd(std::string const & interface_name, std::istream & stream, std::string const & output_path) {
- return gen_systemd_config(parse_config(interface_name, stream), output_path);
+ SystemdConfig wg2nd(std::string const & interface_name, std::istream & stream,
+ std::filesystem::path const & keyfile_or_output_path, std::optional<std::string> const & filename) {
+ return gen_systemd_config(parse_config(interface_name, stream), keyfile_or_output_path, filename);
}
}
diff --git a/src/wg2sd.hpp b/src/wg2nd.hpp
index e80a284..7bf7f54 100644
--- a/src/wg2sd.hpp
+++ b/src/wg2nd.hpp
@@ -9,7 +9,7 @@
#include <cstdint>
-namespace wg2sd {
+namespace wg2nd {
struct Interface {
// File name, or defaults to "wg"
@@ -134,8 +134,14 @@ namespace wg2sd {
Config parse_config(std::string const & interface_name, std::istream & stream);
- SystemdConfig gen_systemd_config(Config const & cfg, std::string const & output_path);
+ SystemdConfig gen_systemd_config(
+ Config const & cfg,
+ std::filesystem::path const & keyfile_or_output_path,
+ std::optional<std::string> const & filename
+ );
- SystemdConfig wg2sd(std::string const & interface_name, std::istream & stream, std::string const & output_path);
+ SystemdConfig wg2nd(std::string const & interface_name, std::istream & stream,
+ std::filesystem::path const & keyfile_or_output_path,
+ std::optional<std::string> const & filename);
};
diff --git a/test/wg2sd_test.cpp b/test/wg2nd_test.cpp
index 5d57ac9..39b0766 100644
--- a/test/wg2sd_test.cpp
+++ b/test/wg2nd_test.cpp
@@ -1,17 +1,17 @@
#include "utest.h"
-#include "wg2sd.hpp"
+#include "wg2nd.hpp"
#include <sstream>
#include <array>
-namespace wg2sd {
+namespace wg2nd {
extern bool _is_default_route(std::string const & cidr);
extern bool _is_ipv4_route(std::string const & cidr);
};
-using namespace wg2sd;
+using namespace wg2nd;
-UTEST(wg2sd, ip_helpers) {
+UTEST(wg2nd, ip_helpers) {
std::array<std::string, 8> default_routes = {
"0/0",
@@ -121,7 +121,7 @@ const char * INVALID_CONFIG = (
);
-UTEST(wg2sd, parses_config) {
+UTEST(wg2nd, parses_config) {
// CONFIG1
std::istringstream ss { CONFIG1 };