diff --git a/tfclient/src/config.rs b/tfclient/src/config.rs index ff14660..8882b26 100644 --- a/tfclient/src/config.rs +++ b/tfclient/src/config.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use std::error::Error; use std::fs; use std::net::{Ipv4Addr, SocketAddrV4}; +use ipnet::{IpNet, Ipv4Net}; use log::{debug, info}; @@ -101,8 +102,27 @@ pub fn save_cdata(instance: &str, data: TFClientData) -> Result<(), Box>, - pub lighthouse: Option + #[serde(skip_serializing_if = "is_none")] + pub lighthouse: Option, + #[serde(skip_serializing_if = "is_none")] + pub listen: Option, + #[serde(skip_serializing_if = "is_none")] + pub punchy: Option, + #[serde(default = "cipher_aes")] + #[serde(skip_serializing_if = "is_cipher_aes")] + pub cipher: NebulaConfigCipher, + #[serde(default = "empty_vec")] + #[serde(skip_serializing_if = "is_empty_vec")] + pub preferred_ranges: Vec, + #[serde(skip_serializing_if = "is_none")] + pub relay: Option, + #[serde(skip_serializing_if = "is_none")] + pub tun: Option, + #[serde(skip_serializing_if = "is_none")] + pub logging: Option, + } #[derive(Serialize, Deserialize)] @@ -111,35 +131,231 @@ pub struct NebulaConfigPki { pub cert: String, pub key: String, #[serde(default = "empty_vec")] + #[serde(skip_serializing_if = "is_empty_vec")] pub blocklist: Vec, #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] pub disconnect_invalid: bool } #[derive(Serialize, Deserialize)] pub struct NebulaConfigLighthouse { #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] pub am_lighthouse: bool, #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] pub serve_dns: bool, + #[serde(skip_serializing_if = "is_none")] pub dns: Option, #[serde(default = "u32_10")] + #[serde(skip_serializing_if = "is_u32_10")] pub interval: u32, #[serde(default = "empty_vec")] + #[serde(skip_serializing_if = "is_empty_vec")] pub hosts: Vec, #[serde(default = "empty_hashmap")] + #[serde(skip_serializing_if = "is_empty_hashmap")] + pub remote_allow_list: HashMap, + #[serde(default = "empty_hashmap")] + #[serde(skip_serializing_if = "is_empty_hashmap")] + pub local_allow_list: HashMap, // `interfaces` is not supported } #[derive(Serialize, Deserialize)] pub struct NebulaConfigLighthouseDns { pub host: Ipv4Addr, #[serde(default = "u16_53")] + #[serde(skip_serializing_if = "is_u16_53")] pub port: u16 } +#[derive(Serialize, Deserialize)] +pub struct NebulaConfigListen { + #[serde(default = "ipv4_0000")] + #[serde(skip_serializing_if = "is_ipv4_0000")] + pub host: Ipv4Addr, + #[serde(default = "u16_0")] + #[serde(skip_serializing_if = "is_u16_0")] + pub port: u16, + #[serde(default = "u32_64")] + #[serde(skip_serializing_if = "is_u32_64")] + pub batch: u32, + #[serde(skip_serializing_if = "is_none")] + pub read_buffer: Option, + #[serde(skip_serializing_if = "is_none")] + pub write_buffer: Option +} + +#[derive(Serialize, Deserialize)] +pub struct NebulaConfigPunchy { + #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] + pub punch: bool, + #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] + pub respond: bool, + #[serde(default = "string_1s")] + #[serde(skip_serializing_if = "is_string_1s")] + pub delay: String +} + +#[derive(Serialize, Deserialize)] +pub enum NebulaConfigCipher { + #[serde(rename = "aes")] + Aes, + #[serde(rename = "chachapoly")] + ChaChaPoly +} + +#[derive(Serialize, Deserialize)] +pub struct NebulaConfigRelay { + #[serde(default = "empty_vec")] + #[serde(skip_serializing_if = "is_empty_vec")] + pub relays: Vec, + #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] + pub am_relay: bool, + #[serde(default = "bool_true")] + #[serde(skip_serializing_if = "is_bool_true")] + pub use_relays: bool +} + +#[derive(Serialize, Deserialize)] +pub struct NebulaConfigTun { + #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] + pub disabled: bool, + #[serde(skip_serializing_if = "is_none")] + pub dev: Option, + #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] + pub drop_local_broadcast: bool, + #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] + pub drop_multicast: bool, + #[serde(default = "u64_500")] + #[serde(skip_serializing_if = "is_u64_500")] + pub tx_queue: u64, + #[serde(default = "u64_1300")] + #[serde(skip_serializing_if = "is_u64_1300")] + pub mtu: u64, + #[serde(default = "empty_vec")] + #[serde(skip_serializing_if = "is_empty_vec")] + pub routes: Vec, + #[serde(default = "empty_vec")] + #[serde(skip_serializing_if = "is_empty_vec")] + pub unsafe_routes: Vec +} + +#[derive(Serialize, Deserialize)] +pub struct NebulaConfigTunRouteOverride { + pub mtu: u64, + pub route: Ipv4Net +} + +#[derive(Serialize, Deserialize)] +pub struct NebulaConfigTunUnsafeRoute { + pub route: Ipv4Net, + pub via: Ipv4Addr, + #[serde(default = "u64_1300")] + #[serde(skip_serializing_if = "is_u64_1300")] + pub mtu: u64, + #[serde(default = "i64_100")] + #[serde(skip_serializing_if = "is_i64_100")] + pub metric: i64 +} + +#[derive(Serialize, Deserialize)] +pub struct NebulaConfigLogging { + #[serde(default = "loglevel_info")] + #[serde(skip_serializing_if = "is_loglevel_info")] + pub level: NebulaConfigLoggingLevel, + #[serde(default = "format_text")] + #[serde(skip_serializing_if = "is_format_text")] + pub format: NebulaConfigLoggingFormat, + #[serde(default = "bool_false")] + #[serde(skip_serializing_if = "is_bool_false")] + pub disable_timestamp: bool, + #[serde(default = "timestamp")] + #[serde(skip_serializing_if = "is_timestamp")] + pub timestamp_format: String +} + +#[derive(Serialize, Deserialize)] +pub enum NebulaConfigLoggingLevel { + #[serde(rename = "panic")] + Panic, + #[serde(rename = "fatal")] + Fatal, + #[serde(rename = "error")] + Error, + #[serde(rename = "warning")] + Warning, + #[serde(rename = "info")] + Info, + #[serde(rename = "debug")] + Debug +} + +#[derive(Serialize, Deserialize)] +pub enum NebulaConfigLoggingFormat { + #[serde(rename = "json")] + Json, + #[serde(rename = "text")] + Text +} + // Default values for serde fn empty_vec() -> Vec { vec![] } +fn is_empty_vec(v: &Vec) -> bool { v.is_empty() } + fn empty_hashmap() -> HashMap { HashMap::new() } +fn is_empty_hashmap(h: &HashMap) -> bool { h.is_empty() } + fn bool_false() -> bool { false } +fn is_bool_false(b: &bool) -> bool { !*b } + +fn bool_true() -> bool { true } +fn is_bool_true(b: &bool) -> bool { *b } + fn u16_53() -> u16 { 53 } -fn u32_10() -> u32 { 10 } \ No newline at end of file +fn is_u16_53(u: &u16) -> bool { *u == 53 } + +fn u32_10() -> u32 { 10 } +fn is_u32_10(u: &u32) -> bool { *u == 10 } + +fn ipv4_0000() -> Ipv4Addr { Ipv4Addr::new(0, 0, 0, 0) } +fn is_ipv4_0000(i: &Ipv4Addr) -> bool { *i == ipv4_0000() } + +fn u16_0() -> u16 { 0 } +fn is_u16_0(u: &u16) -> bool { *u == 0 } + +fn u32_64() -> u32 { 64 } +fn is_u32_64(u: &u32) -> bool { *u == 64 } + +fn string_1s() -> String { "1s".to_string() } +fn is_string_1s(s: &str) -> bool { s == "1s" } + +fn cipher_aes() -> NebulaConfigCipher { NebulaConfigCipher::Aes } +fn is_cipher_aes(c: &NebulaConfigCipher) -> bool { matches!(c, NebulaConfigCipher::Aes) } + +fn u64_500() -> u64 { 500 } +fn is_u64_500(u: &u64) -> bool { *u == 500 } + +fn u64_1300() -> u64 { 1300 } +fn is_u64_1300(u: &u64) -> bool { *u == 1300 } + +fn i64_100() -> i64 { 100 } +fn is_i64_100(i: &i64) -> bool { *i == 100 } + +fn loglevel_info() -> NebulaConfigLoggingLevel { NebulaConfigLoggingLevel::Info } +fn is_loglevel_info(l: &NebulaConfigLoggingLevel) -> bool { matches!(l, NebulaConfigLoggingLevel::Info) } + +fn format_text() -> NebulaConfigLoggingFormat { NebulaConfigLoggingFormat::Text } +fn is_format_text(f: &NebulaConfigLoggingFormat) -> bool { matches!(f, NebulaConfigLoggingFormat::Text) } + +fn timestamp() -> String { "2006-01-02T15:04:05Z07:00".to_string() } +fn is_timestamp(s: &str) -> bool { s == "2006-01-02T15:04:05Z07:00" } + +fn is_none(o: &Option) -> bool { o.is_none() } \ No newline at end of file