Add support for ini parsing
This commit is contained in:
parent
3ba0004370
commit
59ddc36f2c
11 changed files with 300 additions and 32 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -6,3 +6,7 @@ target/
|
||||||
|
|
||||||
.DS_STORE
|
.DS_STORE
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
burrow.sock
|
||||||
|
burrow.db
|
||||||
|
tmp/
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/jpsim/SourceKitten.git",
|
"location" : "https://github.com/jpsim/SourceKitten.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "b6dc09ee51dfb0c66e042d2328c017483a1a5d56",
|
"revision" : "fd4df99170f5e9d7cf9aa8312aa8506e0e7a44e7",
|
||||||
"version" : "0.34.1"
|
"version" : "0.35.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -32,8 +32,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/apple/swift-argument-parser.git",
|
"location" : "https://github.com/apple/swift-argument-parser.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "8f4d2753f0e4778c76d5f05ad16c74f707390531",
|
"revision" : "fee6933f37fde9a5e12a1e4aeaa93fe60116ff2a",
|
||||||
"version" : "1.2.3"
|
"version" : "1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -41,8 +41,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/apple/swift-syntax.git",
|
"location" : "https://github.com/apple/swift-syntax.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "64889f0c732f210a935a0ad7cda38f77f876262d",
|
"revision" : "303e5c5c36d6a558407d364878df131c3546fad8",
|
||||||
"version" : "509.1.1"
|
"version" : "510.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
"location" : "https://github.com/realm/SwiftLint.git",
|
"location" : "https://github.com/realm/SwiftLint.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"branch" : "main",
|
"branch" : "main",
|
||||||
"revision" : "7595ad3fafc1a31086dc40ba01fd898bf6b42d5f"
|
"revision" : "b42f6ffe77159aed1060bf607212a0410c7623b8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
72
Cargo.lock
generated
72
Cargo.lock
generated
|
|
@ -353,6 +353,7 @@ dependencies = [
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"ring",
|
"ring",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
|
"rust-ini",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
@ -586,6 +587,26 @@ dependencies = [
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-random"
|
||||||
|
version = "0.1.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
||||||
|
dependencies = [
|
||||||
|
"const-random-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-random-macro"
|
||||||
|
version = "0.1.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"once_cell",
|
||||||
|
"tiny-keccak",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "constant_time_eq"
|
name = "constant_time_eq"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
|
@ -641,6 +662,12 @@ version = "0.8.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crunchy"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|
@ -699,6 +726,15 @@ dependencies = [
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dlv-list"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
|
||||||
|
dependencies = [
|
||||||
|
"const-random",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dyn-clone"
|
name = "dyn-clone"
|
||||||
version = "1.0.16"
|
version = "1.0.16"
|
||||||
|
|
@ -1601,6 +1637,16 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-multimap"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
|
||||||
|
dependencies = [
|
||||||
|
"dlv-list",
|
||||||
|
"hashbrown 0.14.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|
@ -1947,6 +1993,17 @@ dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-ini"
|
||||||
|
version = "0.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d625ed57d8f49af6cfa514c42e1a71fadcff60eb0b1c517ff82fe41aa025b41"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"ordered-multimap",
|
||||||
|
"trim-in-place",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.23"
|
version = "0.1.23"
|
||||||
|
|
@ -2347,6 +2404,15 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiny-keccak"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||||
|
dependencies = [
|
||||||
|
"crunchy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
|
@ -2627,6 +2693,12 @@ dependencies = [
|
||||||
"tracing-log 0.2.0",
|
"tracing-log 0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "trim-in-place"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "try-lock"
|
name = "try-lock"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ clap = { version = "4.4", features = ["derive"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-log = "0.1"
|
tracing-log = "0.1"
|
||||||
tracing-oslog = { git = "https://github.com/Stormshield-robinc/tracing-oslog" }
|
tracing-oslog = { git = "https://github.com/Stormshield-robinc/tracing-oslog" }
|
||||||
tracing-subscriber = { version = "0.3" , features = ["std", "env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["std", "env-filter"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
@ -51,6 +51,7 @@ once_cell = "1.19"
|
||||||
console-subscriber = { version = "0.2.0", optional = true }
|
console-subscriber = { version = "0.2.0", optional = true }
|
||||||
console = "0.15.8"
|
console = "0.15.8"
|
||||||
toml = "0.8.12"
|
toml = "0.8.12"
|
||||||
|
rust-ini = "0.21.0"
|
||||||
|
|
||||||
[dependencies.rusqlite]
|
[dependencies.rusqlite]
|
||||||
version = "0.31.0"
|
version = "0.31.0"
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use crate::{
|
||||||
ServerConfig,
|
ServerConfig,
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
},
|
},
|
||||||
database::{get_connection, load_interface, dump_interface},
|
database::{dump_interface, get_connection, load_interface},
|
||||||
wireguard::{Config, Interface},
|
wireguard::{Config, Interface},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -116,10 +116,10 @@ impl DaemonInstance {
|
||||||
.await?;
|
.await?;
|
||||||
Ok(DaemonResponseData::None)
|
Ok(DaemonResponseData::None)
|
||||||
}
|
}
|
||||||
DaemonCommand::AddConfigToml(config_toml) => {
|
DaemonCommand::AddConfig(cfig_raw) => {
|
||||||
let conn = get_connection(self.db_path.as_deref())?;
|
let conn = get_connection(self.db_path.as_deref())?;
|
||||||
let cfig = Config::from_toml(&config_toml)?;
|
let cfig = Config::from_content_fmt(&cfig_raw.content, &cfig_raw.fmt)?;
|
||||||
let _if_id = dump_interface(&conn, &cfig)?;
|
let _if_id = dump_interface(&conn, &cfig, cfig_raw.interface_id)?;
|
||||||
Ok(DaemonResponseData::None)
|
Ok(DaemonResponseData::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@ use serde::{Deserialize, Serialize};
|
||||||
use tun::TunOptions;
|
use tun::TunOptions;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
||||||
#[serde(tag="method", content="params")]
|
#[serde(tag = "method", content = "params")]
|
||||||
pub enum DaemonCommand {
|
pub enum DaemonCommand {
|
||||||
Start(DaemonStartOptions),
|
Start(DaemonStartOptions),
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
ServerConfig,
|
ServerConfig,
|
||||||
Stop,
|
Stop,
|
||||||
ReloadConfig(String),
|
ReloadConfig(String),
|
||||||
AddConfigToml(String),
|
AddConfig(AddConfigOptions),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
|
|
@ -18,6 +18,13 @@ pub struct DaemonStartOptions {
|
||||||
pub tun: TunOptions,
|
pub tun: TunOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
|
pub struct AddConfigOptions {
|
||||||
|
pub content: String,
|
||||||
|
pub fmt: String,
|
||||||
|
pub interface_id: Option<i64>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct DaemonRequest {
|
pub struct DaemonRequest {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,24 @@ pub fn load_interface(conn: &Connection, interface_id: &str) -> Result<Config> {
|
||||||
Ok(Config { interface: iface, peers })
|
Ok(Config { interface: iface, peers })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_interface(conn: &Connection, config: &Config) -> Result<i64> {
|
pub fn dump_interface(
|
||||||
|
conn: &Connection,
|
||||||
|
config: &Config,
|
||||||
|
interface_id: Option<i64>,
|
||||||
|
) -> Result<i64> {
|
||||||
|
let interface_id = if let Some(id) = interface_id {
|
||||||
|
let mut stmt = conn.prepare("INSERT INTO wg_interface (private_key, dns, address, listen_port, mtu, id) VALUES (?, ?, ?, ?, ?, ?)")?;
|
||||||
|
let cif = &config.interface;
|
||||||
|
stmt.execute(params![
|
||||||
|
cif.private_key,
|
||||||
|
to_lst(&cif.dns),
|
||||||
|
to_lst(&cif.address),
|
||||||
|
cif.listen_port,
|
||||||
|
cif.mtu,
|
||||||
|
id
|
||||||
|
])?;
|
||||||
|
id
|
||||||
|
} else {
|
||||||
let mut stmt = conn.prepare("INSERT INTO wg_interface (private_key, dns, address, listen_port, mtu) VALUES (?, ?, ?, ?, ?)")?;
|
let mut stmt = conn.prepare("INSERT INTO wg_interface (private_key, dns, address, listen_port, mtu) VALUES (?, ?, ?, ?, ?)")?;
|
||||||
let cif = &config.interface;
|
let cif = &config.interface;
|
||||||
stmt.execute(params![
|
stmt.execute(params![
|
||||||
|
|
@ -102,7 +119,9 @@ pub fn dump_interface(conn: &Connection, config: &Config) -> Result<i64> {
|
||||||
cif.listen_port,
|
cif.listen_port,
|
||||||
cif.mtu
|
cif.mtu
|
||||||
])?;
|
])?;
|
||||||
let interface_id = conn.last_insert_rowid();
|
conn.last_insert_rowid()
|
||||||
|
};
|
||||||
|
|
||||||
let mut stmt = conn.prepare("INSERT INTO wg_peer (interface_id, public_key, preshared_key, allowed_ips, endpoint) VALUES (?, ?, ?, ?, ?)")?;
|
let mut stmt = conn.prepare("INSERT INTO wg_peer (interface_id, public_key, preshared_key, allowed_ips, endpoint) VALUES (?, ?, ?, ?, ?)")?;
|
||||||
for peer in &config.peers {
|
for peer in &config.peers {
|
||||||
stmt.execute(params![
|
stmt.execute(params![
|
||||||
|
|
@ -121,7 +140,7 @@ pub fn get_connection(path: Option<&Path>) -> Result<Connection> {
|
||||||
if !p.exists() {
|
if !p.exists() {
|
||||||
let conn = Connection::open(p)?;
|
let conn = Connection::open(p)?;
|
||||||
initialize_tables(&conn)?;
|
initialize_tables(&conn)?;
|
||||||
dump_interface(&conn, &Config::default())?;
|
dump_interface(&conn, &Config::default(), None)?;
|
||||||
return Ok(conn);
|
return Ok(conn);
|
||||||
}
|
}
|
||||||
Ok(Connection::open(p)?)
|
Ok(Connection::open(p)?)
|
||||||
|
|
@ -129,8 +148,6 @@ pub fn get_connection(path: Option<&Path>) -> Result<Connection> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -138,7 +155,7 @@ mod tests {
|
||||||
let conn = Connection::open_in_memory().unwrap();
|
let conn = Connection::open_in_memory().unwrap();
|
||||||
initialize_tables(&conn).unwrap();
|
initialize_tables(&conn).unwrap();
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
dump_interface(&conn, &config).unwrap();
|
dump_interface(&conn, &config, None).unwrap();
|
||||||
let loaded = load_interface(&conn, "1").unwrap();
|
let loaded = load_interface(&conn, "1").unwrap();
|
||||||
assert_eq!(config, loaded);
|
assert_eq!(config, loaded);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
|
use std::{borrow::Cow, path::PathBuf};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Args, Parser, Subcommand};
|
||||||
|
|
||||||
|
use crate::daemon::rpc::request::AddConfigOptions;
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||||
mod daemon;
|
mod daemon;
|
||||||
pub(crate) mod tracing;
|
pub(crate) mod tracing;
|
||||||
|
|
@ -47,6 +51,16 @@ enum Commands {
|
||||||
ServerConfig,
|
ServerConfig,
|
||||||
/// Reload Config
|
/// Reload Config
|
||||||
ReloadConfig(ReloadConfigArgs),
|
ReloadConfig(ReloadConfigArgs),
|
||||||
|
/// Add Server Config
|
||||||
|
AddConfig(AddServerConfigArgs),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Args)]
|
||||||
|
struct AddServerConfigArgs {
|
||||||
|
#[clap(short, long)]
|
||||||
|
path: PathBuf,
|
||||||
|
#[clap(short, long)]
|
||||||
|
interface_id: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
@ -59,7 +73,12 @@ struct ReloadConfigArgs {
|
||||||
struct StartArgs {}
|
struct StartArgs {}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
struct DaemonArgs {}
|
struct DaemonArgs {
|
||||||
|
#[clap(long, short)]
|
||||||
|
socket_path: Option<PathBuf>,
|
||||||
|
#[clap(long, short)]
|
||||||
|
db_path: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||||
async fn try_start() -> Result<()> {
|
async fn try_start() -> Result<()> {
|
||||||
|
|
@ -132,6 +151,24 @@ async fn try_reloadconfig(interface_id: String) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||||
|
async fn try_add_server_config(path: &PathBuf, interface_id: Option<i64>) -> Result<()> {
|
||||||
|
let mut client = DaemonClient::new().await?;
|
||||||
|
let ext = path
|
||||||
|
.extension()
|
||||||
|
.map(|e| e.to_string_lossy())
|
||||||
|
.unwrap_or_else(|| Cow::Borrowed("toml"));
|
||||||
|
let content = std::fs::read_to_string(path)?;
|
||||||
|
let res = client
|
||||||
|
.send_command(DaemonCommand::AddConfig(AddConfigOptions {
|
||||||
|
content,
|
||||||
|
fmt: ext.to_string(),
|
||||||
|
interface_id,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
|
@ -139,12 +176,20 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
match &cli.command {
|
match &cli.command {
|
||||||
Commands::Start(..) => try_start().await?,
|
Commands::Start(_) => try_start().await?,
|
||||||
Commands::Stop => try_stop().await?,
|
Commands::Stop => try_stop().await?,
|
||||||
Commands::Daemon(_) => daemon::daemon_main(None, None, None).await?,
|
Commands::Daemon(daemon_args) => {
|
||||||
|
daemon::daemon_main(
|
||||||
|
daemon_args.socket_path.as_ref().map(|p| p.as_path()),
|
||||||
|
daemon_args.db_path.as_ref().map(|p| p.as_path()),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
}
|
||||||
Commands::ServerInfo => try_serverinfo().await?,
|
Commands::ServerInfo => try_serverinfo().await?,
|
||||||
Commands::ServerConfig => try_serverconfig().await?,
|
Commands::ServerConfig => try_serverconfig().await?,
|
||||||
Commands::ReloadConfig(args) => try_reloadconfig(args.interface_id.clone()).await?,
|
Commands::ReloadConfig(args) => try_reloadconfig(args.interface_id.clone()).await?,
|
||||||
|
Commands::AddConfig(args) => try_add_server_config(&args.path, args.interface_id).await?,
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@ use std::{net::ToSocketAddrs, str::FromStr};
|
||||||
use anyhow::{anyhow, Error, Result};
|
use anyhow::{anyhow, Error, Result};
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{engine::general_purpose, Engine};
|
||||||
use fehler::throws;
|
use fehler::throws;
|
||||||
|
use ini::{Ini, Properties};
|
||||||
use ip_network::IpNetwork;
|
use ip_network::IpNetwork;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use x25519_dalek::{PublicKey, StaticSecret};
|
use x25519_dalek::{PublicKey, StaticSecret};
|
||||||
|
|
||||||
|
use super::inifield::IniField;
|
||||||
use crate::wireguard::{Interface as WgInterface, Peer as WgPeer};
|
use crate::wireguard::{Interface as WgInterface, Peer as WgPeer};
|
||||||
|
|
||||||
#[throws]
|
#[throws]
|
||||||
|
|
@ -53,6 +55,7 @@ pub struct Interface {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
#[serde(rename = "Peer")]
|
||||||
pub peers: Vec<Peer>,
|
pub peers: Vec<Peer>,
|
||||||
pub interface: Interface, // Support for multiple interfaces?
|
pub interface: Interface, // Support for multiple interfaces?
|
||||||
}
|
}
|
||||||
|
|
@ -115,10 +118,69 @@ impl Default for Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn props_get<T>(props: &Properties, key: &str) -> T
|
||||||
|
where
|
||||||
|
T: From<IniField>,
|
||||||
|
{
|
||||||
|
IniField::from(props.get(key)).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&Properties> for Interface {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(props: &Properties) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
private_key: props_get(props, "PrivateKey"),
|
||||||
|
address: props_get(props, "Address"),
|
||||||
|
listen_port: props_get(props, "ListenPort"),
|
||||||
|
dns: props_get(props, "DNS"),
|
||||||
|
mtu: props_get(props, "MTU"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&Properties> for Peer {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(props: &Properties) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
public_key: props_get(props, "PublicKey"),
|
||||||
|
preshared_key: props_get(props, "PresharedKey"),
|
||||||
|
allowed_ips: props_get(props, "AllowedIPs"),
|
||||||
|
endpoint: props_get(props, "Endpoint"),
|
||||||
|
persistent_keepalive: props_get(props, "PersistentKeepalive"),
|
||||||
|
name: props_get(props, "Name"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn from_toml(toml: &str) -> Result<Self> {
|
pub fn from_toml(toml: &str) -> Result<Self> {
|
||||||
toml::from_str(toml).map_err(Into::into)
|
toml::from_str(toml).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_ini(ini: &str) -> Result<Self> {
|
||||||
|
let ini = Ini::load_from_str(ini)?;
|
||||||
|
let interface = ini
|
||||||
|
.section(Some("Interface"))
|
||||||
|
.ok_or(anyhow!("Interface section not found"))?;
|
||||||
|
let peers = ini.section_all(Some("Peer"));
|
||||||
|
Ok(Self {
|
||||||
|
interface: Interface::try_from(interface)?,
|
||||||
|
peers: peers
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| Peer::try_from(v))
|
||||||
|
.collect::<Result<Vec<Peer>>>()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_content_fmt(content: &str, fmt: &str) -> Result<Self> {
|
||||||
|
match fmt {
|
||||||
|
"toml" => Self::from_toml(content),
|
||||||
|
"ini" | "conf" => Self::from_ini(content),
|
||||||
|
_ => Err(anyhow::anyhow!("Unsupported format: {}", fmt)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
59
burrow/src/wireguard/inifield.rs
Normal file
59
burrow/src/wireguard/inifield.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
pub struct IniField(String);
|
||||||
|
|
||||||
|
impl FromStr for IniField {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(Self(s.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IniField> for Vec<String> {
|
||||||
|
fn from(field: IniField) -> Self {
|
||||||
|
field.0.split(",").map(|s| s.to_string()).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IniField> for u32 {
|
||||||
|
fn from(value: IniField) -> Self {
|
||||||
|
value.0.parse().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IniField> for Option<u32> {
|
||||||
|
fn from(value: IniField) -> Self {
|
||||||
|
Some(value.0.parse().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IniField> for String {
|
||||||
|
fn from(value: IniField) -> Self {
|
||||||
|
value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IniField> for Option<String> {
|
||||||
|
fn from(value: IniField) -> Self {
|
||||||
|
Some(value.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<Option<T>> for IniField
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
fn from(value: Option<T>) -> Self {
|
||||||
|
match value {
|
||||||
|
Some(v) => Self(v.to_string()),
|
||||||
|
None => Self("".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IniField {
|
||||||
|
fn new(value: &str) -> Self {
|
||||||
|
Self(value.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod config;
|
pub mod config;
|
||||||
mod iface;
|
mod iface;
|
||||||
|
mod inifield;
|
||||||
mod noise;
|
mod noise;
|
||||||
mod pcb;
|
mod pcb;
|
||||||
mod peer;
|
mod peer;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue