summaryrefslogtreecommitdiffhomepage
path: root/talpid-macos
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2025-05-28 17:37:36 +0200
committerDavid Lönnhager <david.l@mullvad.net>2025-06-09 14:52:36 +0200
commita6f99ee822d4ec40594bb2ce89498526bc0cf453 (patch)
treee7b77f3df6b61ccc538b221b8d209bfe70246d06 /talpid-macos
parentbcca08c804560b4d2413fdfd3e3df8413330fae9 (diff)
downloadmullvadvpn-a6f99ee822d4ec40594bb2ce89498526bc0cf453.tar.xz
mullvadvpn-a6f99ee822d4ec40594bb2ce89498526bc0cf453.zip
Set SO_REUSEADDR on local DNS resolver socket
This fixes an issue where bind() fails due to other sockets Co-authored-by: Joakim Hulthe <joakim.hulthe@mullvad.net>
Diffstat (limited to 'talpid-macos')
-rw-r--r--talpid-macos/Cargo.toml4
-rw-r--r--talpid-macos/src/lib.rs3
-rw-r--r--talpid-macos/src/net.rs45
3 files changed, 51 insertions, 1 deletions
diff --git a/talpid-macos/Cargo.toml b/talpid-macos/Cargo.toml
index 7b910f5e6d..0b4caa4258 100644
--- a/talpid-macos/Cargo.toml
+++ b/talpid-macos/Cargo.toml
@@ -11,5 +11,7 @@ rust-version.workspace = true
workspace = true
[target.'cfg(target_os="macos")'.dependencies]
+anyhow.workspace = true
+log.workspace = true
libc = "0.2.172"
-log = { workspace = true }
+tokio = { workspace = true, features = ["process"] }
diff --git a/talpid-macos/src/lib.rs b/talpid-macos/src/lib.rs
index 5a282660d3..1dad718685 100644
--- a/talpid-macos/src/lib.rs
+++ b/talpid-macos/src/lib.rs
@@ -9,3 +9,6 @@ pub mod process;
/// OS bindings generated by 'generate_bindings.rs'
#[allow(non_camel_case_types)]
mod bindings;
+
+/// Networking utilities
+pub mod net;
diff --git a/talpid-macos/src/net.rs b/talpid-macos/src/net.rs
new file mode 100644
index 0000000000..5eff2f6878
--- /dev/null
+++ b/talpid-macos/src/net.rs
@@ -0,0 +1,45 @@
+use anyhow::{anyhow, bail, Context};
+use std::net::IpAddr;
+use tokio::process::Command;
+
+/// Adds an alias to a network interface.
+pub async fn add_alias(interface: &str, addr: IpAddr) -> anyhow::Result<()> {
+ let context = || anyhow!("Failed to add interface {interface} alias {addr}");
+ let output = Command::new("ifconfig")
+ .args([interface, "alias", &format!("{addr}"), "up"])
+ .output()
+ .await
+ .context("Failed to spawn ifconfig")
+ .with_context(context)?;
+
+ if !output.status.success() {
+ bail!(
+ "{}: Non-zero exit code from ifconfig: {}",
+ context(),
+ output.status
+ );
+ }
+
+ Ok(())
+}
+
+/// Removes an alias from a network interface.
+pub async fn remove_alias(interface: &str, addr: IpAddr) -> anyhow::Result<()> {
+ let context = || anyhow!("Failed to remove interface {interface} alias {addr}");
+ let output = Command::new("ifconfig")
+ .args([interface, "delete", &format!("{addr}")])
+ .output()
+ .await
+ .context("Failed to spawn ifconfig")
+ .with_context(context)?;
+
+ if !output.status.success() {
+ bail!(
+ "{}: Non-zero exit code from ifconfig: {}",
+ context(),
+ output.status
+ );
+ }
+
+ Ok(())
+}