use std::collections::HashMap;
use super::device::DeviceState;
use super::openvpn::OpenVpnConfig;
use super::saved_connection::VpnSecretFlags;
use super::wireguard::WireGuardConfig;
use uuid::Uuid;
pub(crate) mod sealed {
pub trait Sealed {}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum VpnKind {
Plugin,
WireGuard,
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum OpenVpnConnectionType {
Tls,
StaticKey,
Password,
PasswordTls,
}
impl OpenVpnConnectionType {
#[must_use]
pub fn from_nm_str(s: &str) -> Option<Self> {
match s {
"tls" => Some(Self::Tls),
"static-key" => Some(Self::StaticKey),
"password" => Some(Self::Password),
"password-tls" => Some(Self::PasswordTls),
_ => None,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum VpnType {
WireGuard {
private_key: Option<String>,
peer_public_key: Option<String>,
endpoint: Option<String>,
allowed_ips: Vec<String>,
persistent_keepalive: Option<u32>,
},
OpenVpn {
remote: Option<String>,
connection_type: Option<OpenVpnConnectionType>,
user_name: Option<String>,
ca: Option<String>,
cert: Option<String>,
key: Option<String>,
ta: Option<String>,
password_flags: VpnSecretFlags,
},
OpenConnect {
gateway: Option<String>,
user_name: Option<String>,
protocol: Option<String>,
password_flags: VpnSecretFlags,
},
StrongSwan {
address: Option<String>,
method: Option<String>,
user_name: Option<String>,
certificate: Option<String>,
password_flags: VpnSecretFlags,
},
Pptp {
gateway: Option<String>,
user_name: Option<String>,
password_flags: VpnSecretFlags,
},
L2tp {
gateway: Option<String>,
user_name: Option<String>,
password_flags: VpnSecretFlags,
ipsec_enabled: bool,
},
Generic {
service_type: String,
data: HashMap<String, String>,
secrets: HashMap<String, String>,
user_name: Option<String>,
password_flags: VpnSecretFlags,
},
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum VpnConfiguration {
WireGuard(WireGuardConfig),
OpenVpn(Box<OpenVpnConfig>),
}
impl From<WireGuardConfig> for VpnConfiguration {
fn from(config: WireGuardConfig) -> Self {
Self::WireGuard(config)
}
}
impl From<OpenVpnConfig> for VpnConfiguration {
fn from(config: OpenVpnConfig) -> Self {
Self::OpenVpn(Box::new(config))
}
}
impl sealed::Sealed for VpnConfiguration {}
impl VpnConfig for VpnConfiguration {
fn vpn_kind(&self) -> VpnKind {
match self {
Self::WireGuard(_) => VpnKind::WireGuard,
Self::OpenVpn(_) => VpnKind::Plugin,
}
}
fn name(&self) -> &str {
match self {
Self::WireGuard(c) => &c.name,
Self::OpenVpn(c) => &c.name,
}
}
fn dns(&self) -> Option<&[String]> {
match self {
Self::WireGuard(c) => c.dns.as_deref(),
Self::OpenVpn(c) => c.dns.as_deref(),
}
}
fn mtu(&self) -> Option<u32> {
match self {
Self::WireGuard(c) => c.mtu,
Self::OpenVpn(c) => c.mtu,
}
}
fn uuid(&self) -> Option<Uuid> {
match self {
Self::WireGuard(c) => c.uuid,
Self::OpenVpn(c) => c.uuid,
}
}
}
pub trait VpnConfig: sealed::Sealed + Send + Sync + std::fmt::Debug {
fn vpn_kind(&self) -> VpnKind;
fn name(&self) -> &str;
fn dns(&self) -> Option<&[String]>;
fn mtu(&self) -> Option<u32>;
fn uuid(&self) -> Option<Uuid>;
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct VpnConnection {
pub uuid: String,
pub id: String,
pub name: String,
pub vpn_type: VpnType,
pub state: DeviceState,
pub interface: Option<String>,
pub active: bool,
pub user_name: Option<String>,
pub password_flags: VpnSecretFlags,
pub service_type: String,
pub kind: VpnKind,
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum VpnDetails {
WireGuard {
public_key: Option<String>,
endpoint: Option<String>,
},
OpenVpn {
remote: String,
port: u16,
protocol: String,
cipher: Option<String>,
auth: Option<String>,
compression: Option<String>,
},
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct VpnConnectionInfo {
pub name: String,
pub vpn_kind: VpnKind,
pub state: DeviceState,
pub interface: Option<String>,
pub gateway: Option<String>,
pub ip4_address: Option<String>,
pub ip6_address: Option<String>,
pub dns_servers: Vec<String>,
pub details: Option<VpnDetails>,
}