summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2021-09-27 10:37:19 +0200
committerDavid Lönnhager <david.l@mullvad.net>2021-09-27 10:37:19 +0200
commit2c56264c4c3d5867c1fae3141687ecd0ef9ca9bc (patch)
tree40f69cf2deb4d178027a28de27187e92eb7fd5d4
parent2d11706b8db091f4eab93789ec042ee27a06f162 (diff)
parente832ffa25c5361f2dd9342745c42d1774d7cd00f (diff)
downloadmullvadvpn-2c56264c4c3d5867c1fae3141687ecd0ef9ca9bc.tar.xz
mullvadvpn-2c56264c4c3d5867c1fae3141687ecd0ef9ca9bc.zip
Merge branch 'refactor-cli-grpc-types'
-rw-r--r--mullvad-cli/src/cmds/bridge.rs135
-rw-r--r--mullvad-cli/src/cmds/relay.rs277
-rw-r--r--mullvad-cli/src/location.rs24
-rw-r--r--mullvad-management-interface/proto/management_interface.proto4
-rw-r--r--mullvad-management-interface/src/types.rs544
5 files changed, 481 insertions, 503 deletions
diff --git a/mullvad-cli/src/cmds/bridge.rs b/mullvad-cli/src/cmds/bridge.rs
index 0599c7aef6..17e62f3197 100644
--- a/mullvad-cli/src/cmds/bridge.rs
+++ b/mullvad-cli/src/cmds/bridge.rs
@@ -1,14 +1,16 @@
use crate::{location, new_rpc_client, Command, Error, Result};
use clap::{value_t, values_t};
-use mullvad_management_interface::types::{
- bridge_settings::{Type as BridgeSettingsType, *},
- bridge_state::State as BridgeStateType,
- BridgeSettings, BridgeState, RelayLocation,
+use mullvad_management_interface::types;
+use mullvad_types::relay_constraints::{
+ BridgeConstraints, BridgeSettings, BridgeState, Constraint, LocationConstraint,
};
-use talpid_types::net::openvpn::SHADOWSOCKS_CIPHERS;
+use talpid_types::net::openvpn::{self, SHADOWSOCKS_CIPHERS};
-use std::net::{IpAddr, SocketAddr};
+use std::{
+ convert::TryFrom,
+ net::{IpAddr, SocketAddr},
+};
pub struct Bridge;
@@ -199,19 +201,23 @@ impl Bridge {
async fn handle_get() -> Result<()> {
let mut rpc = new_rpc_client().await?;
let settings = rpc.get_settings(()).await?.into_inner();
- Self::print_state(settings.bridge_state.unwrap());
- match settings.bridge_settings.unwrap().r#type.unwrap() {
- BridgeSettingsType::Local(local_proxy) => Self::print_local_proxy(&local_proxy),
- BridgeSettingsType::Remote(remote_proxy) => Self::print_remote_proxy(&remote_proxy),
- BridgeSettingsType::Shadowsocks(shadowsocks_proxy) => {
- Self::print_shadowsocks_proxy(&shadowsocks_proxy)
- }
- BridgeSettingsType::Normal(constraints) => {
- println!(
- "Bridge constraints - {}, {}",
- location::format_location(constraints.location.as_ref()),
- location::format_providers(&constraints.providers)
- );
+ let bridge_settings = BridgeSettings::try_from(settings.bridge_settings.unwrap()).unwrap();
+ println!(
+ "Bridge state - {}",
+ BridgeState::try_from(settings.bridge_state.unwrap()).unwrap()
+ );
+ match bridge_settings {
+ BridgeSettings::Custom(proxy) => match proxy {
+ openvpn::ProxySettings::Local(local_proxy) => Self::print_local_proxy(&local_proxy),
+ openvpn::ProxySettings::Remote(remote_proxy) => {
+ Self::print_remote_proxy(&remote_proxy)
+ }
+ openvpn::ProxySettings::Shadowsocks(shadowsocks_proxy) => {
+ Self::print_shadowsocks_proxy(&shadowsocks_proxy)
+ }
+ },
+ BridgeSettings::Normal(constraints) => {
+ println!("Bridge constraints - {}", constraints)
}
};
Ok(())
@@ -234,56 +240,58 @@ impl Bridge {
}
async fn update_bridge_settings(
- location: Option<RelayLocation>,
+ location: Option<types::RelayLocation>,
providers: Option<Vec<String>>,
) -> Result<()> {
let mut rpc = new_rpc_client().await?;
let settings = rpc.get_settings(()).await?.into_inner();
- let bridge_settings = settings.bridge_settings.unwrap();
- let constraints = match bridge_settings.r#type.unwrap() {
- BridgeSettingsType::Normal(mut constraints) => {
+ let bridge_settings = BridgeSettings::try_from(settings.bridge_settings.unwrap()).unwrap();
+ let constraints = match bridge_settings {
+ BridgeSettings::Normal(mut constraints) => {
if let Some(new_location) = location {
- constraints.location = Some(new_location);
+ constraints.location = Constraint::<LocationConstraint>::from(new_location);
}
if let Some(new_providers) = providers {
- constraints.providers = new_providers;
+ constraints.providers =
+ types::try_providers_constraint_from_proto(&new_providers).unwrap();
}
constraints
}
_ => {
- let location = location.unwrap_or_default();
- let providers = providers.unwrap_or_default();
+ let location = Constraint::<LocationConstraint>::from(location.unwrap_or_default());
+ let providers =
+ types::try_providers_constraint_from_proto(&providers.unwrap_or_default())
+ .unwrap();
BridgeConstraints {
- location: Some(location),
+ location,
providers,
}
}
};
- rpc.set_bridge_settings(BridgeSettings {
- r#type: Some(BridgeSettingsType::Normal(constraints)),
- })
+ rpc.set_bridge_settings(
+ types::BridgeSettings::try_from(BridgeSettings::Normal(constraints)).unwrap(),
+ )
.await?;
Ok(())
}
async fn handle_set_bridge_state(matches: &clap::ArgMatches<'_>) -> Result<()> {
let state = match matches.value_of("policy").unwrap() {
- "auto" => BridgeStateType::Auto as i32,
- "on" => BridgeStateType::On as i32,
- "off" => BridgeStateType::Off as i32,
+ "auto" => BridgeState::Auto,
+ "on" => BridgeState::On,
+ "off" => BridgeState::Off,
_ => unreachable!(),
};
let mut rpc = new_rpc_client().await?;
- rpc.set_bridge_state(BridgeState { state }).await?;
+ rpc.set_bridge_state(types::BridgeState::from(state))
+ .await?;
Ok(())
}
async fn handle_bridge_set_custom_settings(matches: &clap::ArgMatches<'_>) -> Result<()> {
- use talpid_types::net::openvpn;
-
if let Some(args) = matches.subcommand_matches("local") {
let local_port =
value_t!(args.value_of("local-port"), u16).unwrap_or_else(|e| e.exit());
@@ -296,19 +304,15 @@ impl Bridge {
port: local_port,
peer: SocketAddr::new(remote_ip, remote_port),
};
- let prost_proxy = LocalProxySettings {
- port: local_proxy.port as u32,
- peer: local_proxy.peer.to_string(),
- };
let packed_proxy = openvpn::ProxySettings::Local(local_proxy);
if let Err(error) = openvpn::validate_proxy_settings(&packed_proxy) {
panic!("{}", error);
}
let mut rpc = new_rpc_client().await?;
- rpc.set_bridge_settings(BridgeSettings {
- r#type: Some(BridgeSettingsType::Local(prost_proxy)),
- })
+ rpc.set_bridge_settings(types::BridgeSettings::from(BridgeSettings::Custom(
+ packed_proxy,
+ )))
.await?;
} else if let Some(args) = matches.subcommand_matches("remote") {
let remote_ip =
@@ -325,29 +329,19 @@ impl Bridge {
}),
_ => None,
};
- let prost_auth = auth.clone().map(|auth| RemoteProxyAuth {
- username: auth.username.clone(),
- password: auth.password.clone(),
- });
-
let proxy = openvpn::RemoteProxySettings {
address: SocketAddr::new(remote_ip, remote_port),
auth,
};
- let prost_proxy = RemoteProxySettings {
- address: proxy.address.to_string(),
- auth: prost_auth,
- };
-
let packed_proxy = openvpn::ProxySettings::Remote(proxy);
if let Err(error) = openvpn::validate_proxy_settings(&packed_proxy) {
panic!("{}", error);
}
let mut rpc = new_rpc_client().await?;
- rpc.set_bridge_settings(BridgeSettings {
- r#type: Some(BridgeSettingsType::Remote(prost_proxy)),
- })
+ rpc.set_bridge_settings(types::BridgeSettings::from(BridgeSettings::Custom(
+ packed_proxy,
+ )))
.await?;
} else if let Some(args) = matches.subcommand_matches("shadowsocks") {
let remote_ip =
@@ -362,21 +356,15 @@ impl Bridge {
password,
cipher,
};
- let prost_proxy = ShadowsocksProxySettings {
- peer: proxy.peer.to_string(),
- password: proxy.password.clone(),
- cipher: proxy.cipher.clone(),
- };
-
let packed_proxy = openvpn::ProxySettings::Shadowsocks(proxy);
if let Err(error) = openvpn::validate_proxy_settings(&packed_proxy) {
panic!("{}", error);
}
let mut rpc = new_rpc_client().await?;
- rpc.set_bridge_settings(BridgeSettings {
- r#type: Some(BridgeSettingsType::Shadowsocks(prost_proxy)),
- })
+ rpc.set_bridge_settings(types::BridgeSettings::from(BridgeSettings::Custom(
+ packed_proxy,
+ )))
.await?;
} else {
unreachable!("unhandled proxy type");
@@ -386,22 +374,13 @@ impl Bridge {
Ok(())
}
- fn print_state(state: BridgeState) {
- let state = match BridgeStateType::from_i32(state.state).expect("unknown bridge state") {
- BridgeStateType::Auto => "auto",
- BridgeStateType::On => "on",
- BridgeStateType::Off => "off",
- };
- println!("Bridge state - {}", state);
- }
-
- fn print_local_proxy(proxy: &LocalProxySettings) {
+ fn print_local_proxy(proxy: &openvpn::LocalProxySettings) {
println!("proxy: local");
println!(" local port: {}", proxy.port);
println!(" peer address: {}", proxy.peer);
}
- fn print_remote_proxy(proxy: &RemoteProxySettings) {
+ fn print_remote_proxy(proxy: &openvpn::RemoteProxySettings) {
println!("proxy: remote");
println!(" server address: {}", proxy.address);
@@ -413,7 +392,7 @@ impl Bridge {
}
}
- fn print_shadowsocks_proxy(proxy: &ShadowsocksProxySettings) {
+ fn print_shadowsocks_proxy(proxy: &openvpn::ShadowsocksProxySettings) {
println!("proxy: Shadowsocks");
println!(" peer address: {}", proxy.peer);
println!(" password: {}", proxy.password);
diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs
index 80ee09a6c9..62d2f58fb6 100644
--- a/mullvad-cli/src/cmds/relay.rs
+++ b/mullvad-cli/src/cmds/relay.rs
@@ -8,14 +8,8 @@ use std::{
str::FromStr,
};
-use mullvad_management_interface::types::{
- connection_config::{self, OpenvpnConfig, WireguardConfig},
- relay_settings, relay_settings_update, ConnectionConfig, CustomRelaySettings, IpVersion,
- IpVersionConstraint, NormalRelaySettingsUpdate, OpenvpnConstraints, ProviderUpdate,
- RelayListCountry, RelayLocation, RelaySettingsUpdate, TransportPort, TransportProtocol,
- TunnelType, TunnelTypeConstraint, TunnelTypeUpdate, WireguardConstraints,
-};
-use mullvad_types::relay_constraints::Constraint;
+use mullvad_management_interface::types;
+use mullvad_types::relay_constraints::{Constraint, RelaySettings};
use talpid_types::net::all_of_the_internet;
pub struct Relay;
@@ -231,7 +225,7 @@ impl Command for Relay {
}
impl Relay {
- async fn update_constraints(&self, update: RelaySettingsUpdate) -> Result<()> {
+ async fn update_constraints(&self, update: types::RelaySettingsUpdate) -> Result<()> {
let mut rpc = new_rpc_client().await?;
rpc.update_relay_settings(update)
.await
@@ -271,13 +265,13 @@ impl Relay {
(_unknown_tunnel, _) => unreachable!("No set relay command given"),
};
- self.update_constraints(RelaySettingsUpdate {
- r#type: Some(relay_settings_update::Type::Custom(custom_endpoint)),
+ self.update_constraints(types::RelaySettingsUpdate {
+ r#type: Some(types::relay_settings_update::Type::Custom(custom_endpoint)),
})
.await
}
- fn read_custom_openvpn_relay(matches: &clap::ArgMatches<'_>) -> CustomRelaySettings {
+ fn read_custom_openvpn_relay(matches: &clap::ArgMatches<'_>) -> types::CustomRelaySettings {
let host = value_t!(matches.value_of("host"), String).unwrap_or_else(|e| e.exit());
let port = value_t!(matches.value_of("port"), u16).unwrap_or_else(|e| e.exit());
let username = value_t!(matches.value_of("username"), String).unwrap_or_else(|e| e.exit());
@@ -286,21 +280,24 @@ impl Relay {
let protocol = Self::validate_transport_protocol(&protocol);
- CustomRelaySettings {
+ types::CustomRelaySettings {
host,
- config: Some(ConnectionConfig {
- config: Some(connection_config::Config::Openvpn(OpenvpnConfig {
- address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port).to_string(),
- protocol: protocol as i32,
- username,
- password,
- })),
+ config: Some(types::ConnectionConfig {
+ config: Some(types::connection_config::Config::Openvpn(
+ types::connection_config::OpenvpnConfig {
+ address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port)
+ .to_string(),
+ protocol: protocol as i32,
+ username,
+ password,
+ },
+ )),
}),
}
}
- fn read_custom_wireguard_relay(matches: &clap::ArgMatches<'_>) -> CustomRelaySettings {
- use connection_config::wireguard_config;
+ fn read_custom_wireguard_relay(matches: &clap::ArgMatches<'_>) -> types::CustomRelaySettings {
+ use types::connection_config::wireguard_config;
let host = value_t!(matches.value_of("host"), String).unwrap_or_else(|e| e.exit());
let port = value_t!(matches.value_of("port"), u16).unwrap_or_else(|e| e.exit());
@@ -327,33 +324,35 @@ impl Relay {
let private_key = Self::validate_wireguard_key(&private_key_str);
let peer_public_key = Self::validate_wireguard_key(&peer_key_str);
- CustomRelaySettings {
+ types::CustomRelaySettings {
host,
- config: Some(ConnectionConfig {
- config: Some(connection_config::Config::Wireguard(WireguardConfig {
- tunnel: Some(wireguard_config::TunnelConfig {
- private_key: private_key.to_vec(),
- addresses: addresses
- .iter()
- .map(|address| address.to_string())
- .collect(),
- }),
- peer: Some(wireguard_config::PeerConfig {
- public_key: peer_public_key.to_vec(),
- allowed_ips: all_of_the_internet()
- .iter()
- .map(|address| address.to_string())
- .collect(),
- endpoint: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port)
- .to_string(),
- protocol: protocol as i32,
- }),
- ipv4_gateway: ipv4_gateway.to_string(),
- ipv6_gateway: ipv6_gateway
- .as_ref()
- .map(|addr| addr.to_string())
- .unwrap_or_default(),
- })),
+ config: Some(types::ConnectionConfig {
+ config: Some(types::connection_config::Config::Wireguard(
+ types::connection_config::WireguardConfig {
+ tunnel: Some(wireguard_config::TunnelConfig {
+ private_key: private_key.to_vec(),
+ addresses: addresses
+ .iter()
+ .map(|address| address.to_string())
+ .collect(),
+ }),
+ peer: Some(wireguard_config::PeerConfig {
+ public_key: peer_public_key.to_vec(),
+ allowed_ips: all_of_the_internet()
+ .iter()
+ .map(|address| address.to_string())
+ .collect(),
+ endpoint: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port)
+ .to_string(),
+ protocol: protocol as i32,
+ }),
+ ipv4_gateway: ipv4_gateway.to_string(),
+ ipv6_gateway: ipv6_gateway
+ .as_ref()
+ .map(|addr| addr.to_string())
+ .unwrap_or_default(),
+ },
+ )),
}),
}
}
@@ -377,10 +376,10 @@ impl Relay {
key
}
- fn validate_transport_protocol(protocol: &str) -> TransportProtocol {
+ fn validate_transport_protocol(protocol: &str) -> types::TransportProtocol {
match protocol {
- "udp" => TransportProtocol::Udp,
- "tcp" => TransportProtocol::Tcp,
+ "udp" => types::TransportProtocol::Udp,
+ "tcp" => types::TransportProtocol::Tcp,
_ => clap::Error::with_description(
"invalid transport protocol",
clap::ErrorKind::ValueValidation,
@@ -412,15 +411,15 @@ impl Relay {
location.2.hostname, location.1.name, location.0.name
);
- let location_constraint = RelayLocation {
+ let location_constraint = types::RelayLocation {
country: location.0.code.clone(),
city: location.1.code.clone(),
hostname: location.2.hostname.clone(),
};
- self.update_constraints(RelaySettingsUpdate {
- r#type: Some(relay_settings_update::Type::Normal(
- NormalRelaySettingsUpdate {
+ self.update_constraints(types::RelaySettingsUpdate {
+ r#type: Some(types::relay_settings_update::Type::Normal(
+ types::NormalRelaySettingsUpdate {
location: Some(location_constraint),
..Default::default()
},
@@ -482,9 +481,9 @@ impl Relay {
}
}
- self.update_constraints(RelaySettingsUpdate {
- r#type: Some(relay_settings_update::Type::Normal(
- NormalRelaySettingsUpdate {
+ self.update_constraints(types::RelaySettingsUpdate {
+ r#type: Some(types::relay_settings_update::Type::Normal(
+ types::NormalRelaySettingsUpdate {
location: Some(location_constraint),
..Default::default()
},
@@ -503,10 +502,10 @@ impl Relay {
providers
};
- self.update_constraints(RelaySettingsUpdate {
- r#type: Some(relay_settings_update::Type::Normal(
- NormalRelaySettingsUpdate {
- providers: Some(ProviderUpdate { providers }),
+ self.update_constraints(types::RelaySettingsUpdate {
+ r#type: Some(types::relay_settings_update::Type::Normal(
+ types::NormalRelaySettingsUpdate {
+ providers: Some(types::ProviderUpdate { providers }),
..Default::default()
},
)),
@@ -516,10 +515,10 @@ impl Relay {
async fn set_openvpn_constraints(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
let port = parse_transport_port(matches)?;
- self.update_constraints(RelaySettingsUpdate {
- r#type: Some(relay_settings_update::Type::Normal(
- NormalRelaySettingsUpdate {
- openvpn_constraints: Some(OpenvpnConstraints { port }),
+ self.update_constraints(types::RelaySettingsUpdate {
+ r#type: Some(types::relay_settings_update::Type::Normal(
+ types::NormalRelaySettingsUpdate {
+ openvpn_constraints: Some(types::OpenvpnConstraints { port }),
..Default::default()
},
)),
@@ -533,13 +532,15 @@ impl Relay {
let entry_location =
parse_entry_location_constraint(matches.values_of("entry location").unwrap());
- self.update_constraints(RelaySettingsUpdate {
- r#type: Some(relay_settings_update::Type::Normal(
- NormalRelaySettingsUpdate {
- wireguard_constraints: Some(WireguardConstraints {
+ self.update_constraints(types::RelaySettingsUpdate {
+ r#type: Some(types::relay_settings_update::Type::Normal(
+ types::NormalRelaySettingsUpdate {
+ wireguard_constraints: Some(types::WireguardConstraints {
port,
- ip_version: ip_version.option().map(|protocol| IpVersionConstraint {
- protocol: protocol as i32,
+ ip_version: ip_version.option().map(|protocol| {
+ types::IpVersionConstraint {
+ protocol: protocol as i32,
+ }
}),
entry_location,
}),
@@ -552,16 +553,16 @@ impl Relay {
async fn set_tunnel_protocol(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
let tunnel_type = match matches.value_of("tunnel protocol").unwrap() {
- "wireguard" => Some(TunnelType::Wireguard),
- "openvpn" => Some(TunnelType::Openvpn),
+ "wireguard" => Some(types::TunnelType::Wireguard),
+ "openvpn" => Some(types::TunnelType::Openvpn),
"any" => None,
_ => unreachable!(),
};
- self.update_constraints(RelaySettingsUpdate {
- r#type: Some(relay_settings_update::Type::Normal(
- NormalRelaySettingsUpdate {
- tunnel_type: Some(TunnelTypeUpdate {
- tunnel_type: tunnel_type.map(|tunnel_type| TunnelTypeConstraint {
+ self.update_constraints(types::RelaySettingsUpdate {
+ r#type: Some(types::relay_settings_update::Type::Normal(
+ types::NormalRelaySettingsUpdate {
+ tunnel_type: Some(types::TunnelTypeUpdate {
+ tunnel_type: tunnel_type.map(|tunnel_type| types::TunnelTypeConstraint {
tunnel_type: tunnel_type as i32,
}),
}),
@@ -574,71 +575,17 @@ impl Relay {
async fn get(&self) -> Result<()> {
let mut rpc = new_rpc_client().await?;
- let constraints = rpc
+ let relay_settings = rpc
.get_settings(())
.await?
.into_inner()
.relay_settings
.unwrap();
- print!("Current constraints: ");
-
- match constraints.endpoint.unwrap() {
- relay_settings::Endpoint::Normal(settings) => match settings.tunnel_type {
- None => {
- println!(
- "Any tunnel protocol with OpenVPN over {} and WireGuard over {} in {} using {}",
- Self::format_openvpn_constraints(settings.openvpn_constraints.as_ref()),
- Self::format_wireguard_constraints(settings.wireguard_constraints.as_ref()),
- location::format_location(settings.location.as_ref()),
- location::format_providers(&settings.providers)
- );
- }
- Some(constraint) => match TunnelType::from_i32(constraint.tunnel_type).unwrap() {
- TunnelType::Wireguard => {
- println!(
- "WireGuard over {} in {} using {}",
- Self::format_wireguard_constraints(
- settings.wireguard_constraints.as_ref()
- ),
- location::format_location(settings.location.as_ref()),
- location::format_providers(&settings.providers)
- );
- }
- TunnelType::Openvpn => {
- println!(
- "OpenVPN over {} in {} using {}",
- Self::format_openvpn_constraints(settings.openvpn_constraints.as_ref()),
- location::format_location(settings.location.as_ref()),
- location::format_providers(&settings.providers)
- );
- }
- },
- },
-
- relay_settings::Endpoint::Custom(settings) => {
- let config = settings.config.unwrap();
- match config.config.unwrap() {
- connection_config::Config::Openvpn(config) => {
- println!(
- "custom OpenVPN relay - {} {}",
- config.address,
- Self::format_transport_protocol(Some(
- TransportProtocol::from_i32(config.protocol).unwrap()
- )),
- );
- }
- connection_config::Config::Wireguard(config) => {
- let peer = config.peer.unwrap();
- println!(
- "custom WireGuard relay - {} with public key {}",
- peer.endpoint,
- base64::encode(&peer.public_key),
- );
- }
- }
- }
- }
+ print!(
+ "Current constraints: {}",
+ RelaySettings::try_from(relay_settings).unwrap()
+ );
Ok(())
}
@@ -692,37 +639,7 @@ impl Relay {
Ok(())
}
- fn format_transport_protocol(protocol: Option<TransportProtocol>) -> &'static str {
- match protocol {
- None => "any transport protocol",
- Some(TransportProtocol::Udp) => "UDP",
- Some(TransportProtocol::Tcp) => "TCP",
- }
- }
-
- fn format_openvpn_constraints(constraints: Option<&OpenvpnConstraints>) -> String {
- if let Some(constraints) = constraints {
- let ovpn_constraints =
- mullvad_types::relay_constraints::OpenVpnConstraints::try_from(constraints)
- .unwrap();
- format!("{}", ovpn_constraints)
- } else {
- "any port over any transport protocol".to_string()
- }
- }
-
- fn format_wireguard_constraints(constraints: Option<&WireguardConstraints>) -> String {
- if let Some(constraints) = constraints {
- let wg_constraints =
- mullvad_types::relay_constraints::WireguardConstraints::try_from(constraints)
- .unwrap();
- format!("{}", wg_constraints)
- } else {
- "any port over any protocol over IPv4 or IPv6".to_string()
- }
- }
-
- async fn get_filtered_relays() -> Result<Vec<RelayListCountry>> {
+ async fn get_filtered_relays() -> Result<Vec<types::RelayListCountry>> {
let mut rpc = new_rpc_client().await?;
let mut locations = rpc
.get_relay_locations(())
@@ -769,27 +686,27 @@ fn parse_port_constraint(raw_port: &str) -> Result<Constraint<u16>> {
}
}
-fn parse_protocol(raw_protocol: &str) -> Constraint<TransportProtocol> {
+fn parse_protocol(raw_protocol: &str) -> Constraint<types::TransportProtocol> {
match raw_protocol {
"any" => Constraint::Any,
- "udp" => Constraint::Only(TransportProtocol::Udp),
- "tcp" => Constraint::Only(TransportProtocol::Tcp),
+ "udp" => Constraint::Only(types::TransportProtocol::Udp),
+ "tcp" => Constraint::Only(types::TransportProtocol::Tcp),
_ => unreachable!(),
}
}
-fn parse_ip_version_constraint(raw_protocol: &str) -> Constraint<IpVersion> {
+fn parse_ip_version_constraint(raw_protocol: &str) -> Constraint<types::IpVersion> {
match raw_protocol {
"any" => Constraint::Any,
- "4" => Constraint::Only(IpVersion::V4),
- "6" => Constraint::Only(IpVersion::V6),
+ "4" => Constraint::Only(types::IpVersion::V4),
+ "6" => Constraint::Only(types::IpVersion::V6),
_ => unreachable!(),
}
}
fn parse_entry_location_constraint<'a, T: Iterator<Item = &'a str>>(
mut location: T,
-) -> Option<RelayLocation> {
+) -> Option<types::RelayLocation> {
let country = location.next().unwrap();
if country == "none" {
@@ -803,16 +720,16 @@ fn parse_entry_location_constraint<'a, T: Iterator<Item = &'a str>>(
))
}
-fn parse_transport_port(matches: &clap::ArgMatches<'_>) -> Result<Option<TransportPort>> {
+fn parse_transport_port(matches: &clap::ArgMatches<'_>) -> Result<Option<types::TransportPort>> {
let port = parse_port_constraint(matches.value_of("port").unwrap())?;
let protocol = parse_protocol(matches.value_of("transport protocol").unwrap());
match (port, protocol) {
(Constraint::Any, Constraint::Any) => Ok(None),
- (Constraint::Any, Constraint::Only(protocol)) => Ok(Some(TransportPort {
+ (Constraint::Any, Constraint::Only(protocol)) => Ok(Some(types::TransportPort {
protocol: protocol as i32,
- ..TransportPort::default()
+ ..types::TransportPort::default()
})),
- (Constraint::Only(port), Constraint::Only(protocol)) => Ok(Some(TransportPort {
+ (Constraint::Only(port), Constraint::Only(protocol)) => Ok(Some(types::TransportPort {
protocol: protocol as i32,
port: u32::from(port),
})),
diff --git a/mullvad-cli/src/location.rs b/mullvad-cli/src/location.rs
index cadeaa24fe..e4719f7d37 100644
--- a/mullvad-cli/src/location.rs
+++ b/mullvad-cli/src/location.rs
@@ -68,30 +68,6 @@ pub fn get_constraint<T: AsRef<str>>(
}
}
-pub fn format_location(location: Option<&RelayLocation>) -> String {
- if let Some(location) = location {
- if !location.hostname.is_empty() {
- return format!(
- "city {}, {}, hostname {}",
- location.city, location.country, location.hostname
- );
- } else if !location.city.is_empty() {
- return format!("city {}, {}", location.city, location.country);
- } else if !location.country.is_empty() {
- return format!("country {}", location.country);
- }
- }
- "any location".to_string()
-}
-
-pub fn format_providers(providers: &Vec<String>) -> String {
- if !providers.is_empty() {
- format!("provider(s) {}", providers.join(", "))
- } else {
- "any provider".to_string()
- }
-}
-
pub fn country_code_validator<T: AsRef<str>>(code: T) -> std::result::Result<(), String> {
if code.as_ref().len() == 2 || code.as_ref() == "any" {
Ok(())
diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto
index aa59458979..8711ba7b1b 100644
--- a/mullvad-management-interface/proto/management_interface.proto
+++ b/mullvad-management-interface/proto/management_interface.proto
@@ -223,7 +223,6 @@ message BridgeSettings {
}
message RemoteProxySettings {
string address = 1;
- // NOTE: optional
RemoteProxyAuth auth = 2;
}
message RemoteProxyAuth {
@@ -364,7 +363,6 @@ message ConnectionConfig {
TunnelConfig tunnel = 1;
PeerConfig peer = 2;
string ipv4_gateway = 3;
- // NOTE: optional
string ipv6_gateway = 4;
}
@@ -376,11 +374,9 @@ message ConnectionConfig {
message TunnelOptions {
message OpenvpnOptions {
- // NOTE: optional
uint32 mssfix = 1;
}
message WireguardOptions {
- // NOTE: optional
uint32 mtu = 1;
google.protobuf.Duration rotation_interval = 2;
}
diff --git a/mullvad-management-interface/src/types.rs b/mullvad-management-interface/src/types.rs
index 28149c427d..81fdbb0e87 100644
--- a/mullvad-management-interface/src/types.rs
+++ b/mullvad-management-interface/src/types.rs
@@ -2,6 +2,7 @@ pub use prost_types::{Duration, Timestamp};
use mullvad_types::relay_constraints::Constraint;
use std::convert::TryFrom;
+use talpid_types::ErrorExt;
tonic::include_proto!("mullvad_daemon.management_interface");
@@ -734,151 +735,105 @@ impl TryFrom<&OpenvpnConstraints> for mullvad_types::relay_constraints::OpenVpnC
}
}
-impl TryFrom<RelaySettingsUpdate> for mullvad_types::relay_constraints::RelaySettingsUpdate {
+impl TryFrom<RelaySettings> for mullvad_types::relay_constraints::RelaySettings {
type Error = FromProtobufTypeError;
fn try_from(
- settings: RelaySettingsUpdate,
- ) -> Result<mullvad_types::relay_constraints::RelaySettingsUpdate, Self::Error> {
- use mullvad_types::CustomTunnelEndpoint;
- use talpid_types::net::{self, openvpn, wireguard};
-
- use mullvad_types::relay_constraints as mullvad_constraints;
+ settings: RelaySettings,
+ ) -> Result<mullvad_types::relay_constraints::RelaySettings, Self::Error> {
+ use mullvad_types::{relay_constraints as mullvad_constraints, CustomTunnelEndpoint};
+ use talpid_types::net;
let update_value =
settings
- .r#type
+ .endpoint
.clone()
.ok_or(FromProtobufTypeError::InvalidArgument(
"missing relay settings",
))?;
match update_value {
- relay_settings_update::Type::Custom(settings) => {
+ relay_settings::Endpoint::Custom(settings) => {
let config = settings
.config
.ok_or(FromProtobufTypeError::InvalidArgument(
- "missing relay settings",
+ "missing relay connection config",
))?;
- let config = config.config.ok_or(FromProtobufTypeError::InvalidArgument(
- "missing relay settings",
- ))?;
- let config = match config {
- connection_config::Config::Openvpn(config) => {
- let address = match config.address.parse() {
- Ok(address) => address,
- Err(_) => {
- return Err(FromProtobufTypeError::InvalidArgument(
- "invalid address",
- ))
- }
- };
-
- mullvad_types::ConnectionConfig::OpenVpn(openvpn::ConnectionConfig {
- endpoint: net::Endpoint {
- address,
- protocol: try_transport_protocol_from_i32(config.protocol)?,
- },
- username: config.username,
- password: config.password,
- })
- }
- connection_config::Config::Wireguard(config) => {
- let tunnel = config.tunnel.ok_or(
- FromProtobufTypeError::InvalidArgument("missing tunnel config"),
- )?;
-
- // Copy the private key to an array
- if tunnel.private_key.len() != 32 {
- return Err(FromProtobufTypeError::InvalidArgument(
- "invalid private key",
- ));
- }
-
- let mut private_key = [0; 32];
- let buffer = &tunnel.private_key[..private_key.len()];
- private_key.copy_from_slice(buffer);
-
- let peer = config.peer.ok_or(FromProtobufTypeError::InvalidArgument(
- "missing peer config",
- ))?;
-
- // Copy the public key to an array
- if peer.public_key.len() != 32 {
- return Err(FromProtobufTypeError::InvalidArgument(
- "invalid public key",
- ));
- }
-
- let mut public_key = [0; 32];
- let buffer = &peer.public_key[..public_key.len()];
- public_key.copy_from_slice(buffer);
+ let config = mullvad_types::ConnectionConfig::try_from(config)?;
+ Ok(mullvad_constraints::RelaySettings::CustomTunnelEndpoint(
+ CustomTunnelEndpoint {
+ host: settings.host,
+ config,
+ },
+ ))
+ }
- let ipv4_gateway = match config.ipv4_gateway.parse() {
- Ok(address) => address,
- Err(_) => {
- return Err(FromProtobufTypeError::InvalidArgument(
- "invalid IPv4 gateway",
- ))
- }
- };
- let ipv6_gateway = if !config.ipv6_gateway.is_empty() {
- let address = match config.ipv6_gateway.parse() {
- Ok(address) => address,
- Err(_) => {
- return Err(FromProtobufTypeError::InvalidArgument(
- "invalid IPv6 gateway",
- ))
- }
- };
- Some(address)
- } else {
- None
- };
+ relay_settings::Endpoint::Normal(settings) => {
+ let location =
+ Constraint::<mullvad_types::relay_constraints::LocationConstraint>::from(
+ settings
+ .location
+ .ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing relay location",
+ ))?,
+ );
+ let providers = try_providers_constraint_from_proto(&settings.providers)?;
+ let tunnel_protocol = settings
+ .tunnel_type
+ .map(Constraint::<net::TunnelType>::try_from)
+ .transpose()?
+ .unwrap_or(Constraint::Any);
+ let openvpn_constraints =
+ mullvad_constraints::OpenVpnConstraints::try_from(
+ &settings.openvpn_constraints.ok_or(
+ FromProtobufTypeError::InvalidArgument("missing openvpn constraints"),
+ )?,
+ )?;
+ let wireguard_constraints = mullvad_constraints::WireguardConstraints::try_from(
+ &settings.wireguard_constraints.ok_or(
+ FromProtobufTypeError::InvalidArgument("missing wireguard constraints"),
+ )?,
+ )?;
- let endpoint = match peer.endpoint.parse() {
- Ok(address) => address,
- Err(_) => {
- return Err(FromProtobufTypeError::InvalidArgument(
- "invalid peer address",
- ))
- }
- };
+ Ok(mullvad_constraints::RelaySettings::Normal(
+ mullvad_constraints::RelayConstraints {
+ location,
+ providers,
+ tunnel_protocol,
+ wireguard_constraints,
+ openvpn_constraints,
+ },
+ ))
+ }
+ }
+ }
+}
- let mut tunnel_addresses = Vec::new();
- for address in tunnel.addresses {
- let address = address.parse().map_err(|_| {
- FromProtobufTypeError::InvalidArgument("invalid address")
- })?;
- tunnel_addresses.push(address);
- }
+impl TryFrom<RelaySettingsUpdate> for mullvad_types::relay_constraints::RelaySettingsUpdate {
+ type Error = FromProtobufTypeError;
- let mut allowed_ips = Vec::new();
- for address in peer.allowed_ips {
- let address = address.parse().map_err(|_| {
- FromProtobufTypeError::InvalidArgument("invalid address")
- })?;
- allowed_ips.push(address);
- }
+ fn try_from(
+ settings: RelaySettingsUpdate,
+ ) -> Result<mullvad_types::relay_constraints::RelaySettingsUpdate, Self::Error> {
+ use mullvad_types::{relay_constraints as mullvad_constraints, CustomTunnelEndpoint};
+ use talpid_types::net;
- mullvad_types::ConnectionConfig::Wireguard(wireguard::ConnectionConfig {
- tunnel: wireguard::TunnelConfig {
- private_key: wireguard::PrivateKey::from(private_key),
- addresses: tunnel_addresses,
- },
- peer: wireguard::PeerConfig {
- public_key: wireguard::PublicKey::from(public_key),
- allowed_ips,
- endpoint,
- protocol: try_transport_protocol_from_i32(peer.protocol)?,
- },
- exit_peer: None,
- ipv4_gateway,
- ipv6_gateway,
- })
- }
- };
+ let update_value =
+ settings
+ .r#type
+ .clone()
+ .ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing relay settings",
+ ))?;
+ match update_value {
+ relay_settings_update::Type::Custom(settings) => {
+ let config = settings
+ .config
+ .ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing relay connection config",
+ ))?;
+ let config = mullvad_types::ConnectionConfig::try_from(config)?;
Ok(
mullvad_constraints::RelaySettingsUpdate::CustomTunnelEndpoint(
CustomTunnelEndpoint {
@@ -896,107 +851,194 @@ impl TryFrom<RelaySettingsUpdate> for mullvad_types::relay_constraints::RelaySet
let location = settings
.location
.map(Constraint::<mullvad_types::relay_constraints::LocationConstraint>::from);
-
+ let providers = if let Some(ref provider_update) = settings.providers {
+ Some(try_providers_constraint_from_proto(
+ &provider_update.providers,
+ )?)
+ } else {
+ None
+ };
let tunnel_protocol = if let Some(update) = settings.tunnel_type {
- match update.tunnel_type {
- Some(constraint) => match TunnelType::from_i32(constraint.tunnel_type) {
- Some(TunnelType::Openvpn) => {
- Some(Constraint::Only(net::TunnelType::OpenVpn))
- }
- Some(TunnelType::Wireguard) => {
- Some(Constraint::Only(net::TunnelType::Wireguard))
- }
- None => {
- return Err(FromProtobufTypeError::InvalidArgument(
- "invalid tunnel protocol",
- ))
- }
- },
- None => Some(Constraint::Any),
- }
+ Some(
+ update
+ .tunnel_type
+ .map(Constraint::<net::TunnelType>::try_from)
+ .transpose()?
+ .unwrap_or(Constraint::Any),
+ )
} else {
None
};
-
- let openvpn_transport_port =
+ let openvpn_constraints =
if let Some(ref constraints) = settings.openvpn_constraints {
- match &constraints.port {
- Some(port) => {
- Some(mullvad_constraints::TransportPort::try_from(port.clone())?)
- }
- None => None,
- }
+ Some(mullvad_constraints::OpenVpnConstraints::try_from(
+ constraints,
+ )?)
} else {
None
};
- let wireguard_transport_port =
+ let wireguard_constraints =
if let Some(ref constraints) = settings.wireguard_constraints {
- match &constraints.port {
- Some(port) => {
- Some(mullvad_constraints::TransportPort::try_from(port.clone())?)
- }
- None => None,
- }
+ Some(mullvad_constraints::WireguardConstraints::try_from(
+ constraints,
+ )?)
} else {
None
};
+ Ok(mullvad_constraints::RelaySettingsUpdate::Normal(
+ mullvad_constraints::RelayConstraintsUpdate {
+ location,
+ providers,
+ tunnel_protocol,
+ wireguard_constraints,
+ openvpn_constraints,
+ },
+ ))
+ }
+ }
+ }
+}
- let providers = if let Some(ref provider_update) = settings.providers {
- if !provider_update.providers.is_empty() {
- Some(Constraint::Only(
- mullvad_constraints::Providers::new(
- provider_update.providers.clone().into_iter(),
- )
- .map_err(|_| {
- FromProtobufTypeError::InvalidArgument(
- "must specify at least one provider",
- )
- })?,
- ))
- } else {
- Some(Constraint::Any)
+impl TryFrom<TunnelTypeConstraint> for Constraint<talpid_types::net::TunnelType> {
+ type Error = FromProtobufTypeError;
+
+ fn try_from(
+ tunnel_type: TunnelTypeConstraint,
+ ) -> Result<Constraint<talpid_types::net::TunnelType>, Self::Error> {
+ match TunnelType::from_i32(tunnel_type.tunnel_type) {
+ Some(TunnelType::Openvpn) => {
+ Ok(Constraint::Only(talpid_types::net::TunnelType::OpenVpn))
+ }
+ Some(TunnelType::Wireguard) => {
+ Ok(Constraint::Only(talpid_types::net::TunnelType::Wireguard))
+ }
+ None => Err(FromProtobufTypeError::InvalidArgument(
+ "invalid tunnel protocol",
+ )),
+ }
+ }
+}
+
+impl TryFrom<ConnectionConfig> for mullvad_types::ConnectionConfig {
+ type Error = FromProtobufTypeError;
+
+ fn try_from(config: ConnectionConfig) -> Result<mullvad_types::ConnectionConfig, Self::Error> {
+ use talpid_types::net::{self, openvpn, wireguard};
+
+ let config = config.config.ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing connection config",
+ ))?;
+ match config {
+ connection_config::Config::Openvpn(config) => {
+ let address = match config.address.parse() {
+ Ok(address) => address,
+ Err(_) => {
+ return Err(FromProtobufTypeError::InvalidArgument("invalid address"))
}
- } else {
- None
};
- let ip_version = if let Some(ref constraints) = settings.wireguard_constraints {
- match &constraints.ip_version {
- Some(constraint) => match IpVersion::from_i32(constraint.protocol) {
- Some(IpVersion::V4) => Some(net::IpVersion::V4),
- Some(IpVersion::V6) => Some(net::IpVersion::V6),
- None => {
- return Err(FromProtobufTypeError::InvalidArgument(
- "invalid ip protocol version",
- ))
- }
+
+ Ok(mullvad_types::ConnectionConfig::OpenVpn(
+ openvpn::ConnectionConfig {
+ endpoint: net::Endpoint {
+ address,
+ protocol: try_transport_protocol_from_i32(config.protocol)?,
},
- None => None,
+ username: config.username,
+ password: config.password,
+ },
+ ))
+ }
+ connection_config::Config::Wireguard(config) => {
+ let tunnel = config.tunnel.ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing tunnel config",
+ ))?;
+
+ // Copy the private key to an array
+ if tunnel.private_key.len() != 32 {
+ return Err(FromProtobufTypeError::InvalidArgument(
+ "invalid private key",
+ ));
+ }
+
+ let mut private_key = [0; 32];
+ let buffer = &tunnel.private_key[..private_key.len()];
+ private_key.copy_from_slice(buffer);
+
+ let peer = config.peer.ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing peer config",
+ ))?;
+
+ // Copy the public key to an array
+ if peer.public_key.len() != 32 {
+ return Err(FromProtobufTypeError::InvalidArgument("invalid public key"));
+ }
+
+ let mut public_key = [0; 32];
+ let buffer = &peer.public_key[..public_key.len()];
+ public_key.copy_from_slice(buffer);
+
+ let ipv4_gateway = match config.ipv4_gateway.parse() {
+ Ok(address) => address,
+ Err(_) => {
+ return Err(FromProtobufTypeError::InvalidArgument(
+ "invalid IPv4 gateway",
+ ))
}
+ };
+ let ipv6_gateway = if !config.ipv6_gateway.is_empty() {
+ let address = match config.ipv6_gateway.parse() {
+ Ok(address) => address,
+ Err(_) => {
+ return Err(FromProtobufTypeError::InvalidArgument(
+ "invalid IPv6 gateway",
+ ))
+ }
+ };
+ Some(address)
} else {
None
};
- Ok(mullvad_constraints::RelaySettingsUpdate::Normal(
- mullvad_constraints::RelayConstraintsUpdate {
- location,
- providers,
- tunnel_protocol,
- wireguard_constraints: settings.wireguard_constraints.map(|constraints| {
- mullvad_constraints::WireguardConstraints {
- port: Constraint::from(wireguard_transport_port),
- ip_version: Constraint::from(ip_version),
- entry_location: constraints.entry_location.map(
- Constraint::<
- mullvad_types::relay_constraints::LocationConstraint,
- >::from,
- ),
- }
- }),
- openvpn_constraints: settings.openvpn_constraints.map(|_constraints| {
- mullvad_constraints::OpenVpnConstraints {
- port: Constraint::from(openvpn_transport_port),
- }
- }),
+ let endpoint = match peer.endpoint.parse() {
+ Ok(address) => address,
+ Err(_) => {
+ return Err(FromProtobufTypeError::InvalidArgument(
+ "invalid peer address",
+ ))
+ }
+ };
+
+ let mut tunnel_addresses = Vec::new();
+ for address in tunnel.addresses {
+ let address = address
+ .parse()
+ .map_err(|_| FromProtobufTypeError::InvalidArgument("invalid address"))?;
+ tunnel_addresses.push(address);
+ }
+
+ let mut allowed_ips = Vec::new();
+ for address in peer.allowed_ips {
+ let address = address
+ .parse()
+ .map_err(|_| FromProtobufTypeError::InvalidArgument("invalid address"))?;
+ allowed_ips.push(address);
+ }
+
+ Ok(mullvad_types::ConnectionConfig::Wireguard(
+ wireguard::ConnectionConfig {
+ tunnel: wireguard::TunnelConfig {
+ private_key: wireguard::PrivateKey::from(private_key),
+ addresses: tunnel_addresses,
+ },
+ peer: wireguard::PeerConfig {
+ public_key: wireguard::PublicKey::from(public_key),
+ allowed_ips,
+ endpoint,
+ protocol: try_transport_protocol_from_i32(peer.protocol)?,
+ },
+ exit_peer: None,
+ ipv4_gateway,
+ ipv6_gateway,
},
))
}
@@ -1043,20 +1085,7 @@ impl TryFrom<BridgeSettings> for mullvad_types::relay_constraints::BridgeSetting
Constraint::<mullvad_constraints::LocationConstraint>::from(location)
}
};
- let providers = if constraints.providers.is_empty() {
- Constraint::Any
- } else {
- Constraint::Only(
- mullvad_constraints::Providers::new(
- constraints.providers.clone().into_iter(),
- )
- .map_err(|_| {
- FromProtobufTypeError::InvalidArgument(
- "must specify at least one provider",
- )
- })?,
- )
- };
+ let providers = try_providers_constraint_from_proto(&constraints.providers)?;
Ok(mullvad_constraints::BridgeSettings::Normal(
mullvad_constraints::BridgeConstraints {
@@ -1128,6 +1157,73 @@ impl TryFrom<BridgeState> for mullvad_types::relay_constraints::BridgeState {
}
}
+impl TryFrom<TunnelOptions> for mullvad_types::settings::TunnelOptions {
+ type Error = FromProtobufTypeError;
+
+ fn try_from(options: TunnelOptions) -> Result<Self, Self::Error> {
+ use talpid_types::net;
+
+ let openvpn_options = options
+ .openvpn
+ .ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing openvpn tunnel options",
+ ))?;
+ let wireguard_options = options
+ .wireguard
+ .ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing openvpn tunnel options",
+ ))?;
+ let generic_options = options
+ .generic
+ .ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing generic tunnel options",
+ ))?;
+ let dns_options = options
+ .dns_options
+ .ok_or(FromProtobufTypeError::InvalidArgument(
+ "missing tunnel DNS options",
+ ))?;
+
+ Ok(Self {
+ openvpn: net::openvpn::TunnelOptions {
+ mssfix: if openvpn_options.mssfix != 0 {
+ Some(openvpn_options.mssfix as u16)
+ } else {
+ None
+ },
+ },
+ wireguard: mullvad_types::wireguard::TunnelOptions {
+ options: net::wireguard::TunnelOptions {
+ mtu: if wireguard_options.mtu != 0 {
+ Some(wireguard_options.mtu as u16)
+ } else {
+ None
+ },
+ },
+ rotation_interval: wireguard_options
+ .rotation_interval
+ .map(std::time::Duration::try_from)
+ .transpose()
+ .map_err(|_| FromProtobufTypeError::InvalidArgument("invalid duration"))?
+ .map(mullvad_types::wireguard::RotationInterval::try_from)
+ .transpose()
+ .map_err(|error: mullvad_types::wireguard::RotationIntervalError| {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Invalid rotation interval")
+ );
+ FromProtobufTypeError::InvalidArgument("invalid rotation interval")
+ })?,
+ },
+ generic: net::GenericTunnelOptions {
+ enable_ipv6: generic_options.enable_ipv6,
+ },
+ #[cfg(not(target_os = "android"))]
+ dns_options: mullvad_types::settings::DnsOptions::try_from(dns_options)?,
+ })
+ }
+}
+
impl TryFrom<DnsOptions> for mullvad_types::settings::DnsOptions {
type Error = FromProtobufTypeError;
@@ -1207,6 +1303,20 @@ fn try_transport_protocol_from_i32(
.into())
}
+pub fn try_providers_constraint_from_proto(
+ providers: &[String],
+) -> Result<Constraint<mullvad_types::relay_constraints::Providers>, FromProtobufTypeError> {
+ if !providers.is_empty() {
+ Ok(Constraint::Only(
+ mullvad_types::relay_constraints::Providers::new(providers.iter().cloned()).map_err(
+ |_| FromProtobufTypeError::InvalidArgument("must specify at least one provider"),
+ )?,
+ ))
+ } else {
+ Ok(Constraint::Any)
+ }
+}
+
fn convert_providers_constraint(
providers: &Constraint<mullvad_types::relay_constraints::Providers>,
) -> Vec<String> {