summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2023-11-22 16:18:18 +0100
committerDavid Lönnhager <david.l@mullvad.net>2023-11-22 16:18:18 +0100
commitf7eb43c9170176a59019f5ba3eb5bed08c413058 (patch)
tree5e358a22218210c560c44006585cf411d1ddb23b /test
parent6b0b627bc042da11496bd0ced8662557962572ef (diff)
parent56970baac0773952d2153dc0719faa1bc699ad91 (diff)
downloadmullvadvpn-f7eb43c9170176a59019f5ba3eb5bed08c413058.tar.xz
mullvadvpn-f7eb43c9170176a59019f5ba3eb5bed08c413058.zip
Merge branch 'fix-macos-tests' into main
Diffstat (limited to 'test')
-rw-r--r--test/test-manager/src/tests/account.rs3
-rw-r--r--test/test-manager/src/tests/dns.rs84
-rw-r--r--test/test-manager/src/tests/helpers.rs69
-rw-r--r--test/test-manager/src/tests/install.rs10
-rw-r--r--test/test-manager/src/tests/mod.rs1
-rw-r--r--test/test-manager/src/tests/settings.rs42
-rw-r--r--test/test-manager/src/tests/tunnel.rs118
-rw-r--r--test/test-manager/src/tests/tunnel_state.rs67
-rw-r--r--test/test-rpc/src/client.rs18
-rw-r--r--test/test-rpc/src/lib.rs20
-rw-r--r--test/test-runner/src/main.rs26
-rw-r--r--test/test-runner/src/net.rs154
12 files changed, 277 insertions, 335 deletions
diff --git a/test/test-manager/src/tests/account.rs b/test/test-manager/src/tests/account.rs
index 5b1991abb5..92c95346b2 100644
--- a/test/test-manager/src/tests/account.rs
+++ b/test/test-manager/src/tests/account.rs
@@ -107,12 +107,13 @@ pub async fn test_too_many_devices(
)
.await
.unwrap();
- assert!(ui_result.success());
if let Err(error) = clear_devices(&device_client).await {
log::error!("Failed to clear devices: {error}");
}
+ assert!(ui_result.success());
+
Ok(())
}
diff --git a/test/test-manager/src/tests/dns.rs b/test/test-manager/src/tests/dns.rs
index 310d5eb0dc..89755c3fd6 100644
--- a/test/test-manager/src/tests/dns.rs
+++ b/test/test-manager/src/tests/dns.rs
@@ -9,9 +9,12 @@ use mullvad_management_interface::{types, ManagementServiceClient};
use mullvad_types::{relay_constraints::RelaySettings, ConnectionConfig, CustomTunnelEndpoint};
use talpid_types::net::wireguard;
use test_macro::test_function;
-use test_rpc::{Interface, ServiceClient};
+use test_rpc::ServiceClient;
-use super::{helpers::connect_and_wait, Error, TestContext};
+use super::{
+ helpers::{self, connect_and_wait, set_relay_settings},
+ Error, TestContext,
+};
use crate::network_monitor::{
start_packet_monitor_until, start_tunnel_packet_monitor_until, Direction, IpHeaderProtocols,
MonitorOptions,
@@ -22,8 +25,6 @@ use crate::vm::network::{
CUSTOM_TUN_REMOTE_TUN_ADDR, NON_TUN_GATEWAY,
};
-use super::helpers::set_relay_settings;
-
/// How long to wait for expected "DNS queries" to appear
const MONITOR_TIMEOUT: Duration = Duration::from_secs(5);
@@ -47,7 +48,7 @@ pub async fn test_dns_leak_default(
leak_test_dns(
&rpc,
&mut mullvad_client,
- Interface::Tunnel,
+ true,
IpAddr::V4(CUSTOM_TUN_REMOTE_TUN_ADDR),
)
.await
@@ -82,7 +83,7 @@ pub async fn test_dns_leak_custom_public_ip(
.await
.expect("failed to configure DNS server");
- leak_test_dns(&rpc, &mut mullvad_client, Interface::Tunnel, CONFIG_IP).await
+ leak_test_dns(&rpc, &mut mullvad_client, true, CONFIG_IP).await
}
/// Test whether DNS leaks can be produced when using a custom private IP. This test succeeds if and
@@ -114,7 +115,7 @@ pub async fn test_dns_leak_custom_private_ip(
.await
.expect("failed to configure DNS server");
- leak_test_dns(&rpc, &mut mullvad_client, Interface::NonTunnel, CONFIG_IP).await
+ leak_test_dns(&rpc, &mut mullvad_client, false, CONFIG_IP).await
}
/// See whether it is possible to send "DNS queries" to a particular whitelisted destination on
@@ -124,11 +125,9 @@ pub async fn test_dns_leak_custom_private_ip(
async fn leak_test_dns(
rpc: &ServiceClient,
mullvad_client: &mut ManagementServiceClient,
- interface: Interface,
+ use_tun: bool,
whitelisted_dest: IpAddr,
) -> Result<(), Error> {
- let use_tun = interface == Interface::Tunnel;
-
//
// Connect to local wireguard relay
//
@@ -137,24 +136,32 @@ async fn leak_test_dns(
.await
.expect("failed to connect to custom wg relay");
- let guest_ip = rpc
- .get_interface_ip(Interface::NonTunnel)
+ let nontun_iface = rpc
+ .get_default_interface()
+ .await
+ .expect("failed to find non-tun interface");
+ let tunnel_iface = helpers::get_tunnel_interface(mullvad_client.clone())
+ .await
+ .expect("failed to find tunnel interface");
+
+ let nontun_ip = rpc
+ .get_interface_ip(nontun_iface.clone())
.await
.expect("failed to obtain guest IP");
let tunnel_ip = rpc
- .get_interface_ip(Interface::Tunnel)
+ .get_interface_ip(tunnel_iface.clone())
.await
.expect("failed to obtain tunnel IP");
log::debug!("Tunnel (guest) IP: {tunnel_ip}");
- log::debug!("Non-tunnel (guest) IP: {guest_ip}");
+ log::debug!("Non-tunnel (guest) IP: {nontun_ip}");
//
// Spoof DNS packets
//
let tun_bind_addr = SocketAddr::new(tunnel_ip, 0);
- let guest_bind_addr = SocketAddr::new(guest_ip, 0);
+ let nontun_bind_addr = SocketAddr::new(nontun_ip, 0);
let whitelisted_dest = SocketAddr::new(whitelisted_dest, 53);
let blocked_dest_local = "10.64.100.100:53".parse().unwrap();
@@ -216,40 +223,35 @@ async fn leak_test_dns(
// send to allowed dest
spoof_packets(
&rpc,
- Some(Interface::Tunnel),
+ Some(tunnel_iface.clone()),
tun_bind_addr,
whitelisted_dest,
),
spoof_packets(
&rpc,
- Some(Interface::NonTunnel),
- guest_bind_addr,
+ Some(nontun_iface.clone()),
+ nontun_bind_addr,
whitelisted_dest,
),
// send to blocked local dest
spoof_packets(
&rpc,
- Some(Interface::Tunnel),
+ Some(tunnel_iface.clone()),
tun_bind_addr,
blocked_dest_local,
),
spoof_packets(
&rpc,
- Some(Interface::NonTunnel),
- guest_bind_addr,
+ Some(nontun_iface.clone()),
+ nontun_bind_addr,
blocked_dest_local,
),
// send to blocked public dest
+ spoof_packets(&rpc, Some(tunnel_iface), tun_bind_addr, blocked_dest_public,),
spoof_packets(
&rpc,
- Some(Interface::Tunnel),
- tun_bind_addr,
- blocked_dest_public,
- ),
- spoof_packets(
- &rpc,
- Some(Interface::NonTunnel),
- guest_bind_addr,
+ Some(nontun_iface),
+ nontun_bind_addr,
blocked_dest_public,
),
)
@@ -578,17 +580,25 @@ async fn run_dns_config_test<
}
}
- let guest_ip = rpc
- .get_interface_ip(Interface::NonTunnel)
+ let nontun_iface = rpc
+ .get_default_interface()
+ .await
+ .expect("failed to find non-tun interface");
+ let tunnel_iface = helpers::get_tunnel_interface(mullvad_client.clone())
+ .await
+ .expect("failed to find tunnel interface");
+
+ let nontun_ip = rpc
+ .get_interface_ip(nontun_iface)
.await
.expect("failed to obtain guest IP");
let tunnel_ip = rpc
- .get_interface_ip(Interface::Tunnel)
+ .get_interface_ip(tunnel_iface)
.await
.expect("failed to obtain tunnel IP");
log::debug!("Tunnel (guest) IP: {tunnel_ip}");
- log::debug!("Non-tunnel (guest) IP: {guest_ip}");
+ log::debug!("Non-tunnel (guest) IP: {nontun_ip}");
let monitor = create_monitor().await;
@@ -661,19 +671,21 @@ async fn connect_local_wg_relay(mullvad_client: &mut ManagementServiceClient) ->
async fn spoof_packets(
rpc: &ServiceClient,
- interface: Option<Interface>,
+ interface: Option<String>,
bind_addr: SocketAddr,
dest: SocketAddr,
) {
let tcp_rpc = rpc.clone();
+ let tcp_interface = interface.clone();
let tcp_send = async move {
log::debug!("sending to {}/tcp from {}", dest, bind_addr);
- let _ = tcp_rpc.send_tcp(interface, bind_addr, dest).await;
+ let _ = tcp_rpc.send_tcp(tcp_interface, bind_addr, dest).await;
};
let udp_rpc = rpc.clone();
+ let udp_interface = interface.clone();
let udp_send = async move {
log::debug!("sending to {}/udp from {}", dest, bind_addr);
- let _ = udp_rpc.send_udp(interface, bind_addr, dest).await;
+ let _ = udp_rpc.send_udp(udp_interface, bind_addr, dest).await;
};
let _ = tokio::join!(tcp_send, udp_send);
}
diff --git a/test/test-manager/src/tests/helpers.rs b/test/test-manager/src/tests/helpers.rs
index ea876bbbbe..5b1c0a9903 100644
--- a/test/test-manager/src/tests/helpers.rs
+++ b/test/test-manager/src/tests/helpers.rs
@@ -1,7 +1,7 @@
use super::{config::TEST_CONFIG, Error, PING_TIMEOUT, WAIT_FOR_TUNNEL_STATE_TIMEOUT};
use crate::network_monitor::{start_packet_monitor, MonitorOptions};
use futures::StreamExt;
-use mullvad_management_interface::{types, ManagementServiceClient};
+use mullvad_management_interface::{types, ManagementServiceClient, MullvadProxyClient};
use mullvad_types::{
location::Location,
relay_constraints::{
@@ -19,7 +19,7 @@ use std::{
time::Duration,
};
use talpid_types::net::wireguard::{PeerConfig, PrivateKey, TunnelConfig};
-use test_rpc::{package::Package, AmIMullvad, Interface, ServiceClient};
+use test_rpc::{package::Package, AmIMullvad, ServiceClient};
use tokio::time::timeout;
#[macro_export]
@@ -82,17 +82,30 @@ pub async fn using_mullvad_exit(rpc: &ServiceClient) -> bool {
.mullvad_exit_ip
}
+/// Get VPN tunnel interface name
+pub async fn get_tunnel_interface(rpc: ManagementServiceClient) -> Option<String> {
+ let mut client = MullvadProxyClient::from_rpc_client(rpc);
+ match client.get_tunnel_state().await.ok()? {
+ TunnelState::Connecting { endpoint, .. } | TunnelState::Connected { endpoint, .. } => {
+ endpoint.tunnel_interface
+ }
+ _ => None,
+ }
+}
+
/// Sends a number of probes and returns the number of observed packets (UDP, TCP, or ICMP)
pub async fn send_guest_probes(
rpc: ServiceClient,
- interface: Option<Interface>,
+ interface: String,
destination: SocketAddr,
) -> Result<ProbeResult, Error> {
+ const MONITOR_DURATION: Duration = Duration::from_secs(8);
+
let pktmon = start_packet_monitor(
move |packet| packet.destination.ip() == destination.ip(),
MonitorOptions {
direction: Some(crate::network_monitor::Direction::In),
- timeout: Some(Duration::from_secs(3)),
+ timeout: Some(MONITOR_DURATION),
..Default::default()
},
)
@@ -100,7 +113,7 @@ pub async fn send_guest_probes(
let send_handle = tokio::spawn(send_guest_probes_without_monitor(
rpc,
- interface,
+ Some(interface),
destination,
));
@@ -132,12 +145,12 @@ pub async fn send_guest_probes(
/// Send one probe per transport protocol to `destination` without running a packet monitor
pub async fn send_guest_probes_without_monitor(
rpc: ServiceClient,
- interface: Option<Interface>,
+ interface: Option<String>,
destination: SocketAddr,
) {
- let bind_addr = if let Some(interface) = interface {
+ let bind_addr = if let Some(ref interface) = interface {
SocketAddr::new(
- rpc.get_interface_ip(interface)
+ rpc.get_interface_ip(interface.clone())
.await
.expect("failed to obtain interface IP"),
0,
@@ -147,9 +160,19 @@ pub async fn send_guest_probes_without_monitor(
};
let tcp_rpc = rpc.clone();
- let tcp_send = async move { tcp_rpc.send_tcp(interface, bind_addr, destination).await };
+ let tcp_interface = interface.clone();
+ let tcp_send = async move {
+ tcp_rpc
+ .send_tcp(tcp_interface, bind_addr, destination)
+ .await
+ };
let udp_rpc = rpc.clone();
- let udp_send = async move { udp_rpc.send_udp(interface, bind_addr, destination).await };
+ let udp_interface = interface.clone();
+ let udp_send = async move {
+ udp_rpc
+ .send_udp(udp_interface, bind_addr, destination)
+ .await
+ };
let icmp = async move { ping_with_timeout(&rpc, destination.ip(), interface).await };
let _ = tokio::join!(tcp_send, udp_send, icmp);
}
@@ -157,7 +180,7 @@ pub async fn send_guest_probes_without_monitor(
pub async fn ping_with_timeout(
rpc: &ServiceClient,
dest: IpAddr,
- interface: Option<Interface>,
+ interface: Option<String>,
) -> Result<(), Error> {
timeout(PING_TIMEOUT, rpc.send_ping(interface, dest))
.await
@@ -449,30 +472,6 @@ pub fn unreachable_wireguard_tunnel() -> talpid_types::net::wireguard::Connectio
}
}
-/// Randomly select an entry and exit node from the daemon's relay list.
-/// The exit node is distinct from the entry node.
-///
-/// * `mullvad_client` - An interface to the Mullvad daemon.
-/// * `critera` - A function used to determine which relays to include in random selection.
-pub async fn random_entry_and_exit<Filter>(
- mullvad_client: &mut ManagementServiceClient,
- criteria: Filter,
-) -> Result<(Relay, Relay), Error>
-where
- Filter: Fn(&Relay) -> bool,
-{
- use itertools::Itertools;
- // Pluck the first 2 relays and return them as a tuple.
- // This will fail if there are less than 2 relays in the relay list.
- filter_relays(mullvad_client, criteria)
- .await?
- .into_iter()
- .next_tuple()
- .ok_or(Error::Other(
- "failed to randomly select two relays from daemon's relay list".to_string(),
- ))
-}
-
/// Return a filtered version of the daemon's relay list.
///
/// * `mullvad_client` - An interface to the Mullvad daemon.
diff --git a/test/test-manager/src/tests/install.rs b/test/test-manager/src/tests/install.rs
index 04d401a22d..37a89f5fc8 100644
--- a/test/test-manager/src/tests/install.rs
+++ b/test/test-manager/src/tests/install.rs
@@ -11,7 +11,7 @@ use std::{
};
use test_macro::test_function;
use test_rpc::meta::Os;
-use test_rpc::{mullvad_daemon::ServiceStatus, Interface, ServiceClient};
+use test_rpc::{mullvad_daemon::ServiceStatus, ServiceClient};
/// Install the last stable version of the app and verify that it is running.
#[test_function(priority = -200)]
@@ -102,10 +102,14 @@ pub async fn test_upgrade_app(ctx: TestContext, rpc: ServiceClient) -> Result<()
// Begin monitoring outgoing traffic and pinging
//
+ let guest_iface = rpc
+ .get_default_interface()
+ .await
+ .expect("failed to obtain default interface");
let guest_ip = rpc
- .get_interface_ip(Interface::NonTunnel)
+ .get_interface_ip(guest_iface)
.await
- .expect("failed to obtain tunnel IP");
+ .expect("failed to obtain non-tun IP");
log::debug!("Guest IP: {guest_ip}");
log::debug!("Monitoring outgoing traffic");
diff --git a/test/test-manager/src/tests/mod.rs b/test/test-manager/src/tests/mod.rs
index b35f1b9b7a..ada613ca34 100644
--- a/test/test-manager/src/tests/mod.rs
+++ b/test/test-manager/src/tests/mod.rs
@@ -63,6 +63,7 @@ pub enum Error {
#[error(display = "Failed to parse gRPC response")]
InvalidGrpcResponse(#[error(source)] types::FromProtobufTypeError),
+ #[cfg(target_os = "macos")]
#[error(display = "An error occurred: {}", _0)]
Other(String),
}
diff --git a/test/test-manager/src/tests/settings.rs b/test/test-manager/src/tests/settings.rs
index 4c5808f790..aea81028fe 100644
--- a/test/test-manager/src/tests/settings.rs
+++ b/test/test-manager/src/tests/settings.rs
@@ -1,5 +1,5 @@
use super::helpers;
-use super::helpers::{connect_and_wait, disconnect_and_wait, get_tunnel_state, send_guest_probes};
+use super::helpers::{connect_and_wait, get_tunnel_state, send_guest_probes};
use super::{Error, TestContext};
use crate::assert_tunnel_state;
use crate::vm::network::DUMMY_LAN_INTERFACE_IP;
@@ -8,7 +8,7 @@ use mullvad_management_interface::ManagementServiceClient;
use mullvad_types::states::TunnelState;
use std::net::{IpAddr, SocketAddr};
use test_macro::test_function;
-use test_rpc::{Interface, ServiceClient};
+use test_rpc::ServiceClient;
/// Verify that traffic to private IPs is blocked when
/// "local network sharing" is disabled, but not blocked
@@ -46,11 +46,12 @@ pub async fn test_lan(
log::info!("Test whether outgoing LAN traffic is blocked");
+ let default_interface = rpc.get_default_interface().await?;
let detected_probes =
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), lan_destination).await?;
+ send_guest_probes(rpc.clone(), default_interface.clone(), lan_destination).await?;
assert!(
detected_probes.none(),
- "observed unexpected outgoing LAN packets"
+ "observed unexpected outgoing LAN packets: {detected_probes:?}"
);
//
@@ -71,14 +72,12 @@ pub async fn test_lan(
log::info!("Test whether outgoing LAN traffic is blocked");
let detected_probes =
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), lan_destination).await?;
+ send_guest_probes(rpc.clone(), default_interface, lan_destination).await?;
assert!(
detected_probes.all(),
- "did not observe all outgoing LAN packets"
+ "did not observe all outgoing LAN packets: {detected_probes:?}"
);
- disconnect_and_wait(&mut mullvad_client).await?;
-
Ok(())
}
@@ -133,15 +132,20 @@ pub async fn test_lockdown(
// Ensure all destinations are unreachable
//
+ let default_interface = rpc.get_default_interface().await?;
+
let detected_probes =
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), lan_destination).await?;
- assert!(detected_probes.none(), "observed outgoing packets to LAN");
+ send_guest_probes(rpc.clone(), default_interface.clone(), lan_destination).await?;
+ assert!(
+ detected_probes.none(),
+ "observed outgoing packets to LAN: {detected_probes:?}"
+ );
let detected_probes =
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), inet_destination).await?;
+ send_guest_probes(rpc.clone(), default_interface.clone(), inet_destination).await?;
assert!(
detected_probes.none(),
- "observed outgoing packets to internet"
+ "observed outgoing packets to internet: {detected_probes:?}"
);
//
@@ -160,17 +164,17 @@ pub async fn test_lockdown(
//
let detected_probes =
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), lan_destination).await?;
+ send_guest_probes(rpc.clone(), default_interface.clone(), lan_destination).await?;
assert!(
detected_probes.all(),
- "did not observe some outgoing packets"
+ "did not observe some outgoing packets: {detected_probes:?}"
);
let detected_probes =
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), inet_destination).await?;
+ send_guest_probes(rpc.clone(), default_interface.clone(), inet_destination).await?;
assert!(
detected_probes.none(),
- "observed outgoing packets to internet"
+ "observed outgoing packets to internet: {detected_probes:?}"
);
//
@@ -191,10 +195,10 @@ pub async fn test_lockdown(
// Send traffic outside the tunnel to sanity check that the internet is *not* reachable via non-
// tunnel interfaces.
let detected_probes =
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), inet_destination).await?;
+ send_guest_probes(rpc.clone(), default_interface, inet_destination).await?;
assert!(
detected_probes.none(),
- "observed outgoing packets to internet"
+ "observed outgoing packets to internet: {detected_probes:?}"
);
//
@@ -205,7 +209,5 @@ pub async fn test_lockdown(
.await
.expect("failed to disable lockdown mode");
- disconnect_and_wait(&mut mullvad_client).await?;
-
Ok(())
}
diff --git a/test/test-manager/src/tests/tunnel.rs b/test/test-manager/src/tests/tunnel.rs
index 1f1d61670e..6f759d7826 100644
--- a/test/test-manager/src/tests/tunnel.rs
+++ b/test/test-manager/src/tests/tunnel.rs
@@ -10,14 +10,13 @@ use mullvad_types::relay_constraints::{
OpenVpnConstraints, RelayConstraints, RelaySettings, SelectedObfuscation, TransportPort,
Udp2TcpObfuscationSettings, WireguardConstraints,
};
-use mullvad_types::relay_list::{Relay, RelayEndpointData};
use mullvad_types::wireguard;
use pnet_packet::ip::IpNextHeaderProtocols;
use talpid_types::net::{TransportProtocol, TunnelType};
use test_macro::test_function;
use test_rpc::meta::Os;
use test_rpc::mullvad_daemon::ServiceStatus;
-use test_rpc::{Interface, ServiceClient};
+use test_rpc::ServiceClient;
/// Set up an OpenVPN tunnel, UDP as well as TCP.
/// This test fails if a working tunnel cannot be set up.
@@ -123,18 +122,14 @@ pub async fn test_wireguard_tunnel(
Ok(())
}
-/// Use udp2tcp obfuscation. This test connects to a
-/// WireGuard relay over TCP. It fails if no outgoing TCP
-/// traffic to the relay is observed on the expected port.
+/// Use udp2tcp obfuscation. This test connects to a WireGuard relay over TCP. It fails if no
+/// outgoing TCP traffic to the relay is observed on the expected port.
#[test_function]
pub async fn test_udp2tcp_tunnel(
_: TestContext,
rpc: ServiceClient,
mut mullvad_client: ManagementServiceClient,
) -> Result<(), Error> {
- // TODO: check if src <-> target / tcp is observed (only)
- // TODO: ping a public IP on the fake network (not possible using real relay)
-
mullvad_client
.set_obfuscation_settings(types::ObfuscationSettings::from(ObfuscationSettings {
selected_obfuscation: SelectedObfuscation::Udp2Tcp,
@@ -158,18 +153,19 @@ pub async fn test_udp2tcp_tunnel(
connect_and_wait(&mut mullvad_client).await?;
+ let endpoint = match helpers::get_tunnel_state(&mut mullvad_client).await {
+ mullvad_types::states::TunnelState::Connected { endpoint, .. } => endpoint.endpoint,
+ _ => panic!("unexpected tunnel state"),
+ };
+
//
// Set up packet monitor
//
- let guest_ip = rpc
- .get_interface_ip(Interface::NonTunnel)
- .await
- .expect("failed to obtain inet interface IP");
-
let monitor = start_packet_monitor(
move |packet| {
- packet.source.ip() != guest_ip || (packet.protocol == IpNextHeaderProtocols::Tcp)
+ packet.destination.ip() == endpoint.address.ip()
+ && packet.protocol == IpNextHeaderProtocols::Tcp
},
MonitorOptions::default(),
)
@@ -185,9 +181,10 @@ pub async fn test_udp2tcp_tunnel(
);
let monitor_result = monitor.into_result().await.unwrap();
- assert_eq!(monitor_result.discarded_packets, 0);
-
- disconnect_and_wait(&mut mullvad_client).await?;
+ assert!(
+ !monitor_result.packets.is_empty(),
+ "detected no tcp traffic",
+ );
Ok(())
}
@@ -235,22 +232,19 @@ pub async fn test_bridge(
log::info!("Connect to OpenVPN relay via bridge");
- connect_and_wait(&mut mullvad_client)
- .await
- .expect("connect_and_wait");
+ connect_and_wait(&mut mullvad_client).await?;
- let tunnel = helpers::get_tunnel_state(&mut mullvad_client).await;
- let (entry, exit) = match tunnel {
+ let (entry, exit) = match helpers::get_tunnel_state(&mut mullvad_client).await {
mullvad_types::states::TunnelState::Connected { endpoint, .. } => {
(endpoint.proxy.unwrap().endpoint, endpoint.endpoint)
}
- _ => return Err(Error::DaemonError("daemon entered error state".to_string())),
+ _ => panic!("unexpected tunnel state"),
};
log::info!(
- "Selected entry bridge {entry_ip} & exit relay {exit_ip}",
- entry_ip = entry.address.ip().to_string(),
- exit_ip = exit.address.ip().to_string()
+ "Selected entry bridge {entry_addr} & exit relay {exit_addr}",
+ entry_addr = entry.address,
+ exit_addr = exit.address
);
// Start recording outgoing packets. Their destination will be verified
@@ -284,14 +278,11 @@ pub async fn test_bridge(
"detected no traffic to entry server",
);
- disconnect_and_wait(&mut mullvad_client).await?;
-
Ok(())
}
/// Test whether WireGuard multihop works. This fails if:
-/// * No outgoing traffic to the entry relay is
-/// observed from the SUT.
+/// * No outgoing traffic to the entry relay is observed from the SUT.
/// * The conncheck reports an unexpected exit relay.
#[test_function]
pub async fn test_multihop(
@@ -299,24 +290,12 @@ pub async fn test_multihop(
rpc: ServiceClient,
mut mullvad_client: ManagementServiceClient,
) -> Result<(), Error> {
- //
- // Set relays to use
- //
-
- log::info!("Select relay");
- let relay_filter = |relay: &Relay| {
- relay.active && matches!(relay.endpoint_data, RelayEndpointData::Wireguard(_))
- };
- let (entry, exit) = helpers::random_entry_and_exit(&mut mullvad_client, relay_filter).await?;
- let exit_constraint = helpers::into_constraint(&exit);
let wireguard_constraints = WireguardConstraints {
use_multihop: true,
- entry_location: helpers::into_constraint(&entry),
..Default::default()
};
let relay_settings = RelaySettings::Normal(RelayConstraints {
- location: exit_constraint,
wireguard_constraints,
..Default::default()
});
@@ -329,25 +308,32 @@ pub async fn test_multihop(
// Connect
//
- let monitor = start_packet_monitor(
- move |packet| {
- packet.destination.ip() == entry.ipv4_addr_in
- && packet.protocol == IpNextHeaderProtocols::Udp
- },
- MonitorOptions::default(),
- )
- .await;
+ log::info!("Connect using WG multihop");
connect_and_wait(&mut mullvad_client).await?;
+ let (entry, exit) = match helpers::get_tunnel_state(&mut mullvad_client).await {
+ mullvad_types::states::TunnelState::Connected { endpoint, .. } => {
+ (endpoint.entry_endpoint.unwrap(), endpoint.endpoint)
+ }
+ _ => panic!("unexpected tunnel state"),
+ };
+
+ log::info!(
+ "Selected entry {entry_addr} & exit relay {exit_addr}",
+ entry_addr = entry.address,
+ exit_addr = exit.address
+ );
+
//
- // Verify entry IP
+ // Record outgoing packets to the entry relay
//
- log::info!("Verifying entry server");
-
- let monitor_result = monitor.into_result().await.unwrap();
- assert!(!monitor_result.packets.is_empty(), "no matching packets",);
+ let monitor = start_packet_monitor(
+ move |packet| packet.destination.ip() == entry.address.ip(),
+ MonitorOptions::default(),
+ )
+ .await;
//
// Verify exit IP
@@ -358,7 +344,14 @@ pub async fn test_multihop(
"expected Mullvad exit IP"
);
- disconnect_and_wait(&mut mullvad_client).await?;
+ //
+ // Verify entry IP
+ //
+
+ log::info!("Verifying entry server");
+
+ let monitor_result = monitor.into_result().await.unwrap();
+ assert!(!monitor_result.packets.is_empty(), "no matching packets",);
Ok(())
}
@@ -473,7 +466,7 @@ pub async fn test_quantum_resistant_tunnel(
//
connect_and_wait(&mut mullvad_client).await?;
- check_tunnel_psk(&rpc, false).await;
+ check_tunnel_psk(&rpc, &mullvad_client, false).await;
log::info!("Setting tunnel protocol to WireGuard");
@@ -497,7 +490,7 @@ pub async fn test_quantum_resistant_tunnel(
//
connect_and_wait(&mut mullvad_client).await?;
- check_tunnel_psk(&rpc, true).await;
+ check_tunnel_psk(&rpc, &mullvad_client, true).await;
assert!(
helpers::using_mullvad_exit(&rpc).await,
@@ -507,11 +500,14 @@ pub async fn test_quantum_resistant_tunnel(
Ok(())
}
-async fn check_tunnel_psk(rpc: &ServiceClient, should_have_psk: bool) {
+async fn check_tunnel_psk(
+ rpc: &ServiceClient,
+ mullvad_client: &ManagementServiceClient,
+ should_have_psk: bool,
+) {
match rpc.get_os().await.expect("failed to get OS") {
Os::Linux => {
- let name = rpc
- .get_interface_name(Interface::Tunnel)
+ let name = helpers::get_tunnel_interface(mullvad_client.clone())
.await
.expect("failed to get tun name");
let output = rpc
diff --git a/test/test-manager/src/tests/tunnel_state.rs b/test/test-manager/src/tests/tunnel_state.rs
index 87fda3b685..eb78828fd0 100644
--- a/test/test-manager/src/tests/tunnel_state.rs
+++ b/test/test-manager/src/tests/tunnel_state.rs
@@ -1,6 +1,6 @@
use super::helpers::{
- self, connect_and_wait, disconnect_and_wait, get_tunnel_state, send_guest_probes,
- set_relay_settings, unreachable_wireguard_tunnel, wait_for_tunnel_state,
+ self, connect_and_wait, get_tunnel_state, send_guest_probes, set_relay_settings,
+ unreachable_wireguard_tunnel, wait_for_tunnel_state,
};
use super::{ui, Error, TestContext};
use crate::assert_tunnel_state;
@@ -17,7 +17,7 @@ use mullvad_types::{
use std::net::{IpAddr, SocketAddr};
use talpid_types::net::{Endpoint, TransportProtocol, TunnelEndpoint, TunnelType};
use test_macro::test_function;
-use test_rpc::{Interface, ServiceClient};
+use test_rpc::ServiceClient;
/// Verify that outgoing TCP, UDP, and ICMP packets can be observed
/// in the disconnected state. The purpose is mostly to rule prevent
@@ -40,8 +40,13 @@ pub async fn test_disconnected_state(
log::info!("Sending packets to {inet_destination}");
+ let non_tunnel_interface = rpc
+ .get_default_interface()
+ .await
+ .expect("failed to obtain non-tun interface");
+
let detected_probes =
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), inet_destination).await?;
+ send_guest_probes(rpc.clone(), non_tunnel_interface, inet_destination).await?;
assert!(
detected_probes.all(),
"did not see (all) outgoing packets to destination: {detected_probes:?}",
@@ -118,26 +123,31 @@ pub async fn test_connecting_state(
// Leak test
//
+ let non_tunnel_interface = rpc
+ .get_default_interface()
+ .await
+ .expect("failed to obtain non-tun interface");
+
assert!(
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), inet_destination)
+ send_guest_probes(rpc.clone(), non_tunnel_interface.clone(), inet_destination)
.await?
.none(),
"observed unexpected outgoing packets (inet)"
);
assert!(
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), lan_destination)
+ send_guest_probes(rpc.clone(), non_tunnel_interface.clone(), lan_destination)
.await?
.none(),
"observed unexpected outgoing packets (lan)"
);
assert!(
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), inet_dns)
+ send_guest_probes(rpc.clone(), non_tunnel_interface.clone(), inet_dns)
.await?
.none(),
"observed unexpected outgoing packets (DNS, inet)"
);
assert!(
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), lan_dns)
+ send_guest_probes(rpc.clone(), non_tunnel_interface, lan_dns)
.await?
.none(),
"observed unexpected outgoing packets (DNS, lan)"
@@ -145,14 +155,6 @@ pub async fn test_connecting_state(
assert_tunnel_state!(&mut mullvad_client, TunnelState::Connecting { .. });
- //
- // Disconnect
- //
-
- log::info!("Disconnecting");
-
- disconnect_and_wait(&mut mullvad_client).await?;
-
Ok(())
}
@@ -201,39 +203,36 @@ pub async fn test_error_state(
// Leak test
//
+ let default_interface = rpc
+ .get_default_interface()
+ .await
+ .expect("failed to obtain non-tun interface");
+
assert!(
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), inet_destination)
+ send_guest_probes(rpc.clone(), default_interface.clone(), inet_destination)
.await?
.none(),
"observed unexpected outgoing packets (inet)"
);
assert!(
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), lan_destination)
+ send_guest_probes(rpc.clone(), default_interface.clone(), lan_destination)
.await?
.none(),
"observed unexpected outgoing packets (lan)"
);
assert!(
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), inet_dns)
+ send_guest_probes(rpc.clone(), default_interface.clone(), inet_dns)
.await?
.none(),
"observed unexpected outgoing packets (DNS, inet)"
);
assert!(
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), lan_dns)
+ send_guest_probes(rpc.clone(), default_interface, lan_dns)
.await?
.none(),
"observed unexpected outgoing packets (DNS, lan)"
);
- //
- // Disconnect
- //
-
- log::info!("Disconnecting");
-
- disconnect_and_wait(&mut mullvad_client).await?;
-
Ok(())
}
@@ -318,11 +317,15 @@ pub async fn test_connected_state(
log::info!("Test whether outgoing non-tunnel traffic is blocked");
- let detected_probes =
- send_guest_probes(rpc.clone(), Some(Interface::NonTunnel), inet_destination).await?;
+ let nontun_iface = rpc
+ .get_default_interface()
+ .await
+ .expect("failed to find non-tun interface");
+
+ let detected_probes = send_guest_probes(rpc.clone(), nontun_iface, inet_destination).await?;
assert!(
detected_probes.none(),
- "observed unexpected outgoing packets"
+ "observed unexpected outgoing packets: {detected_probes:?}"
);
assert!(
@@ -330,7 +333,5 @@ pub async fn test_connected_state(
"expected Mullvad exit IP"
);
- disconnect_and_wait(&mut mullvad_client).await?;
-
Ok(())
}
diff --git a/test/test-rpc/src/client.rs b/test/test-rpc/src/client.rs
index 387d0a2435..6be77afb40 100644
--- a/test/test-rpc/src/client.rs
+++ b/test/test-rpc/src/client.rs
@@ -17,8 +17,6 @@ pub struct ServiceClient {
client: service::ServiceClient,
}
-// TODO: implement wrapper methods using macro on Service trait
-
impl ServiceClient {
pub fn new(
connection_handle: transport::ConnectionHandle,
@@ -156,7 +154,7 @@ impl ServiceClient {
/// Send TCP packet
pub async fn send_tcp(
&self,
- interface: Option<Interface>,
+ interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), Error> {
@@ -168,7 +166,7 @@ impl ServiceClient {
/// Send UDP packet
pub async fn send_udp(
&self,
- interface: Option<Interface>,
+ interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), Error> {
@@ -180,7 +178,7 @@ impl ServiceClient {
/// Send ICMP
pub async fn send_ping(
&self,
- interface: Option<Interface>,
+ interface: Option<String>,
destination: IpAddr,
) -> Result<(), Error> {
self.client
@@ -196,16 +194,16 @@ impl ServiceClient {
}
/// Returns the IP of the given interface.
- pub async fn get_interface_name(&self, interface: Interface) -> Result<String, Error> {
+ pub async fn get_interface_ip(&self, interface: String) -> Result<IpAddr, Error> {
self.client
- .get_interface_name(tarpc::context::current(), interface)
+ .get_interface_ip(tarpc::context::current(), interface)
.await?
}
- /// Returns the IP of the given interface.
- pub async fn get_interface_ip(&self, interface: Interface) -> Result<IpAddr, Error> {
+ /// Returns the name of the default non-tunnel interface
+ pub async fn get_default_interface(&self) -> Result<String, Error> {
self.client
- .get_interface_ip(tarpc::context::current(), interface)
+ .get_default_interface(tarpc::context::current())
.await?
}
diff --git a/test/test-rpc/src/lib.rs b/test/test-rpc/src/lib.rs
index 2fd4411f49..6968a3c613 100644
--- a/test/test-rpc/src/lib.rs
+++ b/test/test-rpc/src/lib.rs
@@ -55,12 +55,6 @@ pub enum Error {
Timeout,
}
-#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)]
-pub enum Interface {
- Tunnel,
- NonTunnel,
-}
-
/// Response from am.i.mullvad.net
#[derive(Debug, Serialize, Deserialize)]
pub struct AmIMullvad {
@@ -128,29 +122,29 @@ mod service {
/// Send TCP packet
async fn send_tcp(
- interface: Option<Interface>,
+ interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), Error>;
/// Send UDP packet
async fn send_udp(
- interface: Option<Interface>,
+ interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), Error>;
/// Send ICMP
- async fn send_ping(interface: Option<Interface>, destination: IpAddr) -> Result<(), Error>;
+ async fn send_ping(interface: Option<String>, destination: IpAddr) -> Result<(), Error>;
/// Fetch the current location.
async fn geoip_lookup(mullvad_host: String) -> Result<AmIMullvad, Error>;
- /// Returns the name of the given interface.
- async fn get_interface_name(interface: Interface) -> Result<String, Error>;
-
/// Returns the IP of the given interface.
- async fn get_interface_ip(interface: Interface) -> Result<IpAddr, Error>;
+ async fn get_interface_ip(interface: String) -> Result<IpAddr, Error>;
+
+ /// Returns the name of the default interface.
+ async fn get_default_interface() -> Result<String, Error>;
/// Perform DNS resolution.
async fn resolve_hostname(hostname: String) -> Result<Vec<SocketAddr>, Error>;
diff --git a/test/test-runner/src/main.rs b/test/test-runner/src/main.rs
index 8d7991d6fa..ebf0d1e474 100644
--- a/test/test-runner/src/main.rs
+++ b/test/test-runner/src/main.rs
@@ -13,7 +13,7 @@ use test_rpc::{
mullvad_daemon::{ServiceStatus, SOCKET_PATH},
package::Package,
transport::GrpcForwarder,
- AppTrace, Interface, Service,
+ AppTrace, Service,
};
use tokio::sync::broadcast::error::TryRecvError;
use tokio::{
@@ -117,7 +117,7 @@ impl Service for TestServer {
async fn send_tcp(
self,
_: context::Context,
- interface: Option<Interface>,
+ interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), test_rpc::Error> {
@@ -127,7 +127,7 @@ impl Service for TestServer {
async fn send_udp(
self,
_: context::Context,
- interface: Option<Interface>,
+ interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), test_rpc::Error> {
@@ -137,10 +137,10 @@ impl Service for TestServer {
async fn send_ping(
self,
_: context::Context,
- interface: Option<Interface>,
+ interface: Option<String>,
destination: IpAddr,
) -> Result<(), test_rpc::Error> {
- net::send_ping(interface, destination).await
+ net::send_ping(interface.as_ref().map(String::as_str), destination).await
}
async fn geoip_lookup(
@@ -165,20 +165,16 @@ impl Service for TestServer {
.collect())
}
- async fn get_interface_name(
- self,
- _: context::Context,
- interface: Interface,
- ) -> Result<String, test_rpc::Error> {
- Ok(net::get_interface_name(interface).to_owned())
- }
-
async fn get_interface_ip(
self,
_: context::Context,
- interface: Interface,
+ interface: String,
) -> Result<IpAddr, test_rpc::Error> {
- net::get_interface_ip(interface)
+ net::get_interface_ip(&interface).await
+ }
+
+ async fn get_default_interface(self, _: context::Context) -> Result<String, test_rpc::Error> {
+ Ok(net::get_default_interface().to_owned())
}
async fn poll_output(
diff --git a/test/test-runner/src/net.rs b/test/test-runner/src/net.rs
index 851a2f2951..f40aece4c9 100644
--- a/test/test-runner/src/net.rs
+++ b/test/test-runner/src/net.rs
@@ -2,27 +2,14 @@ use socket2::SockAddr;
#[cfg(target_os = "macos")]
use std::{ffi::CString, num::NonZeroU32};
use std::{
+ io::Write,
net::{IpAddr, SocketAddr},
process::Output,
};
-use test_rpc::Interface;
-use tokio::{
- io::AsyncWriteExt,
- net::{TcpStream, UdpSocket},
- process::Command,
-};
-
-#[cfg(target_os = "linux")]
-const TUNNEL_INTERFACE: &str = "wg-mullvad";
-
-#[cfg(target_os = "windows")]
-const TUNNEL_INTERFACE: &str = "Mullvad";
-
-#[cfg(target_os = "macos")]
-const TUNNEL_INTERFACE: &str = "utun3";
+use tokio::process::Command;
pub async fn send_tcp(
- bind_interface: Option<Interface>,
+ bind_interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), test_rpc::Error> {
@@ -36,14 +23,7 @@ pub async fn send_tcp(
test_rpc::Error::SendTcp
})?;
- sock.set_nonblocking(true).map_err(|error| {
- log::error!("Failed to set non-blocking TCP socket: {error}");
- test_rpc::Error::SendTcp
- })?;
-
if let Some(iface) = bind_interface {
- let iface = get_interface_name(iface);
-
#[cfg(target_os = "macos")]
let interface_index = unsafe {
let name = CString::new(iface).unwrap();
@@ -71,35 +51,32 @@ pub async fn send_tcp(
log::trace!("Bind interface {iface} is ignored on Windows")
}
- sock.bind(&SockAddr::from(bind_addr)).map_err(|error| {
- log::error!("Failed to bind TCP socket to {bind_addr}: {error}");
- test_rpc::Error::SendTcp
- })?;
-
log::debug!("Connecting from {bind_addr} to {destination}/TCP");
- sock.connect(&SockAddr::from(destination))
- .map_err(|error| {
- log::error!("Failed to connect to {destination}: {error}");
+ tokio::task::spawn_blocking(move || {
+ sock.bind(&SockAddr::from(bind_addr)).map_err(|error| {
+ log::error!("Failed to bind TCP socket to {bind_addr}: {error}");
test_rpc::Error::SendTcp
})?;
- let std_stream = std::net::TcpStream::from(sock);
- let mut stream = TcpStream::from_std(std_stream).map_err(|error| {
- log::error!("Failed to convert to TCP stream to tokio stream: {error}");
- test_rpc::Error::SendTcp
- })?;
-
- stream.write_all(b"hello").await.map_err(|error| {
- log::error!("Failed to send message to {destination}: {error}");
- test_rpc::Error::SendTcp
- })?;
+ sock.connect(&SockAddr::from(destination))
+ .map_err(|error| {
+ log::error!("Failed to connect to {destination}: {error}");
+ test_rpc::Error::SendTcp
+ })?;
- Ok(())
+ let mut stream = std::net::TcpStream::from(sock);
+ stream.write_all(b"hello").map_err(|error| {
+ log::error!("Failed to send message to {destination}: {error}");
+ test_rpc::Error::SendTcp
+ })
+ })
+ .await
+ .unwrap()
}
pub async fn send_udp(
- bind_interface: Option<Interface>,
+ bind_interface: Option<String>,
bind_addr: SocketAddr,
destination: SocketAddr,
) -> Result<(), test_rpc::Error> {
@@ -113,14 +90,7 @@ pub async fn send_udp(
test_rpc::Error::SendUdp
})?;
- sock.set_nonblocking(true).map_err(|error| {
- log::error!("Failed to set non-blocking UDP socket: {error}");
- test_rpc::Error::SendUdp
- })?;
-
if let Some(iface) = bind_interface {
- let iface = get_interface_name(iface);
-
#[cfg(target_os = "macos")]
let interface_index = unsafe {
let name = CString::new(iface).unwrap();
@@ -148,32 +118,28 @@ pub async fn send_udp(
log::trace!("Bind interface {iface} is ignored on Windows")
}
- sock.bind(&SockAddr::from(bind_addr)).map_err(|error| {
- log::error!("Failed to bind UDP socket to {bind_addr}: {error}");
- test_rpc::Error::SendUdp
- })?;
+ let _ = tokio::task::spawn_blocking(move || {
+ sock.bind(&SockAddr::from(bind_addr)).map_err(|error| {
+ log::error!("Failed to bind UDP socket to {bind_addr}: {error}");
+ test_rpc::Error::SendUdp
+ })?;
- log::debug!("Send message from {bind_addr} to {destination}/UDP");
+ log::debug!("Send message from {bind_addr} to {destination}/UDP");
- let std_socket = std::net::UdpSocket::from(sock);
- let tokio_socket = UdpSocket::from_std(std_socket).map_err(|error| {
- log::error!("Failed to convert to UDP socket to tokio socket: {error}");
- test_rpc::Error::SendUdp
- })?;
-
- tokio_socket
- .send_to(b"hello", destination)
- .await
- .map_err(|error| {
+ let std_socket = std::net::UdpSocket::from(sock);
+ std_socket.send_to(b"hello", destination).map_err(|error| {
log::error!("Failed to send message to {destination}: {error}");
test_rpc::Error::SendUdp
- })?;
+ })
+ })
+ .await
+ .unwrap()?;
Ok(())
}
pub async fn send_ping(
- interface: Option<Interface>,
+ interface: Option<&str>,
destination: IpAddr,
) -> Result<(), test_rpc::Error> {
#[cfg(target_os = "windows")]
@@ -202,22 +168,8 @@ pub async fn send_ping(
cmd.args(["-c", "1"]);
match interface {
- Some(Interface::Tunnel) => {
- log::info!("Pinging {destination} in tunnel");
-
- #[cfg(target_os = "windows")]
- if let Some(source_ip) = source_ip {
- cmd.args(["-S", &source_ip.to_string()]);
- }
-
- #[cfg(target_os = "windows")]
- cmd.args(["-I", TUNNEL_INTERFACE]);
-
- #[cfg(target_os = "macos")]
- cmd.args(["-b", TUNNEL_INTERFACE]);
- }
- Some(Interface::NonTunnel) => {
- log::info!("Pinging {destination} outside tunnel");
+ Some(interface) => {
+ log::info!("Pinging {destination} on interface {interface}");
#[cfg(target_os = "windows")]
if let Some(source_ip) = source_ip {
@@ -225,10 +177,10 @@ pub async fn send_ping(
}
#[cfg(target_os = "linux")]
- cmd.args(["-I", non_tunnel_interface()]);
+ cmd.args(["-I", interface]);
#[cfg(target_os = "macos")]
- cmd.args(["-b", non_tunnel_interface()]);
+ cmd.args(["-b", interface]);
}
None => log::info!("Pinging {destination}"),
}
@@ -250,18 +202,16 @@ pub async fn send_ping(
}
#[cfg(unix)]
-pub fn get_interface_ip(interface: Interface) -> Result<IpAddr, test_rpc::Error> {
+pub async fn get_interface_ip(interface: &str) -> Result<IpAddr, test_rpc::Error> {
// TODO: IPv6
use std::net::Ipv4Addr;
- let alias = get_interface_name(interface);
-
let addrs = nix::ifaddrs::getifaddrs().map_err(|error| {
log::error!("Failed to obtain interfaces: {}", error);
test_rpc::Error::Syscall
})?;
for addr in addrs {
- if addr.interface_name == alias {
+ if addr.interface_name == interface {
if let Some(address) = addr.address {
if let Some(sockaddr) = address.as_sockaddr_in() {
return Ok(IpAddr::V4(Ipv4Addr::from(sockaddr.ip())));
@@ -274,15 +224,8 @@ pub fn get_interface_ip(interface: Interface) -> Result<IpAddr, test_rpc::Error>
Err(test_rpc::Error::InterfaceNotFound)
}
-pub fn get_interface_name(interface: Interface) -> &'static str {
- match interface {
- Interface::Tunnel => TUNNEL_INTERFACE,
- Interface::NonTunnel => non_tunnel_interface(),
- }
-}
-
#[cfg(target_os = "windows")]
-pub fn get_interface_ip(interface: Interface) -> Result<IpAddr, test_rpc::Error> {
+pub async fn get_interface_ip(interface: &str) -> Result<IpAddr, test_rpc::Error> {
// TODO: IPv6
get_interface_ip_for_family(interface, talpid_windows::net::AddressFamily::Ipv4)
@@ -292,24 +235,19 @@ pub fn get_interface_ip(interface: Interface) -> Result<IpAddr, test_rpc::Error>
#[cfg(target_os = "windows")]
fn get_interface_ip_for_family(
- interface: Interface,
+ interface: &str,
family: talpid_windows::net::AddressFamily,
) -> Result<Option<IpAddr>, ()> {
- let interface = match interface {
- Interface::NonTunnel => non_tunnel_interface(),
- Interface::Tunnel => TUNNEL_INTERFACE,
- };
- let interface_alias = talpid_windows::net::luid_from_alias(interface).map_err(|error| {
+ let luid = talpid_windows::net::luid_from_alias(interface).map_err(|error| {
log::error!("Failed to obtain interface LUID: {error}");
})?;
-
- talpid_windows::net::get_ip_address_for_interface(family, interface_alias).map_err(|error| {
+ talpid_windows::net::get_ip_address_for_interface(family, luid).map_err(|error| {
log::error!("Failed to obtain interface IP: {error}");
})
}
#[cfg(target_os = "windows")]
-fn non_tunnel_interface() -> &'static str {
+pub fn get_default_interface() -> &'static str {
use once_cell::sync::OnceCell;
use talpid_platform_metadata::WindowsVersion;
@@ -326,12 +264,12 @@ fn non_tunnel_interface() -> &'static str {
}
#[cfg(target_os = "linux")]
-fn non_tunnel_interface() -> &'static str {
+pub fn get_default_interface() -> &'static str {
"ens3"
}
#[cfg(target_os = "macos")]
-fn non_tunnel_interface() -> &'static str {
+pub fn get_default_interface() -> &'static str {
"en0"
}