aboutsummaryrefslogtreecommitdiff
path: root/src/wg2nd.hpp
blob: fbded13bd7117f6f988b534a0c15c6743c5343d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// SPDX-License-Identifier: GPL-2.0 OR MIT

/*
 * Copyright (C) 2023 Alex David <flu0r1ne@flu0r1ne.net>
 */

#pragma once

#include <istream>
#include <exception>
#include <optional>
#include <string>
#include <vector>
#include <filesystem>

#include <cstdint>

namespace wg2nd {

	enum class ActivationPolicy {
		MANUAL,
		UP,
	};

	struct Interface {
		// File name, or defaults to "wg"
		std::string name;
		// Address=...
		// List of ip addresses to be assigned to the interface
		std::vector<std::string> addresses;
		// PrivateKey=...
		// Base64-encoded private key string
		std::string private_key;
		// MTu=..
		std::string mtu;
		// DNS=...
		// DNS consists of a comma-separated list of IP addresses of DNS servers
		std::vector<std::string> DNS;
		// Table=...
		// By default, wireguard creates routes. This is disabled, when Table=off
		bool should_create_routes;
		// Table number (if specific), 0 if auto
		uint32_t table;
		// ListenPort=...
		// The port number on which the interface will listen
		std::optional<uint16_t> listen_port;
		// PreUp, PostUp, PreDown PostDown
		std::string preup, postup, predown, postdown;
		// SaveConfig
		std::string save_config;

		Interface()
			: should_create_routes { false }
			, table { 0 }
			, listen_port { }
		{ }
	};

	struct Cidr {
		std::string route;
		bool is_default_route;
		bool is_ipv4;
	};

	struct Peer {
		// Endpoint=...
		// IP and port of the peer
		std::string endpoint;
		// PublicKey=...
		std::string public_key;
		// AllowedIPs=...
		// Comma separated list of allowed ips
		// Each allowed ip is a CIDR block
		std::vector<Cidr> allowed_ips;
		// PersistentAlive=...
		std::string persistent_keepalive;
		// PresharedKey=...
		std::string preshared_key;
	};

	struct Config {
		// [Interface]
		Interface intf;
		// [Peer]
		std::vector<Peer> peers;
		// If one of the peers has a default route
		bool has_default_route;

		Config()
			: has_default_route { false }
		{ }
	};

	class ConfigurationException : public std::exception {

		public:

			ConfigurationException(std::string const & message)
				: _message { message }
			{}

			char const * what() const noexcept override {
				return _message.c_str();
			}

		private:
			std::string _message;
	};

	class ParsingException : public ConfigurationException {

		public:

			ParsingException(std::string const & message, std::optional<uint64_t> line_no = {})
				: ConfigurationException(message)
				, _line_no { line_no }
			{}


			std::optional<uint64_t> line_no() const noexcept {
				return _line_no;
			}

		private:
			std::string _message;
			std::optional<uint64_t> _line_no;
	};

	struct SystemdFilespec {
		std::string name;
		std::string contents;
	};

	struct SystemdConfig {
		SystemdFilespec netdev;
		SystemdFilespec network;
		SystemdFilespec private_keyfile;
		std::vector<SystemdFilespec> symmetric_keyfiles;

		std::vector<std::string> warnings;
		std::string firewall;
	};

	std::string interface_name_from_filename(std::filesystem::path config_path);

	Config parse_config(std::string const & interface_name, std::istream & stream);

	SystemdConfig gen_systemd_config(
		Config const & cfg,
		std::filesystem::path const & keyfile_or_output_path,
		std::optional<std::string> const & filename,
		ActivationPolicy activation_policy = ActivationPolicy::MANUAL
	);

	SystemdConfig wg2nd(std::string const & interface_name, std::istream & stream,
		std::filesystem::path const & keyfile_or_output_path,
		std::optional<std::string> const & filename,
		ActivationPolicy activation_policy = ActivationPolicy::MANUAL
	);

};