wgctrl-rs(userspace): gracefully handle stale `.name` files on macOS
* wgctrl-rs(userspace): clean stale namefiles on starting up interface Fixes #114 * wgctrl-rs(userspace): check connectability of interface socket in enumerate()pull/127/head
parent
bbfb11e175
commit
40e8ca68f9
|
@ -3,14 +3,7 @@ use crate::{Backend, Device, DeviceUpdate, InterfaceName, PeerConfig, PeerInfo,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use crate::Key;
|
use crate::Key;
|
||||||
|
|
||||||
use std::{
|
use std::{fs, io::{self, prelude::*, BufReader}, os::unix::net::UnixStream, path::{Path, PathBuf}, process::{Command, Output}, time::{Duration, SystemTime}};
|
||||||
fs,
|
|
||||||
io::{self, prelude::*, BufReader},
|
|
||||||
os::unix::net::UnixStream,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
process::Command,
|
|
||||||
time::{Duration, SystemTime},
|
|
||||||
};
|
|
||||||
|
|
||||||
static VAR_RUN_PATH: &str = "/var/run/wireguard";
|
static VAR_RUN_PATH: &str = "/var/run/wireguard";
|
||||||
static RUN_PATH: &str = "/run/wireguard";
|
static RUN_PATH: &str = "/run/wireguard";
|
||||||
|
@ -66,9 +59,12 @@ pub fn enumerate() -> Result<Vec<InterfaceName>, io::Error> {
|
||||||
for entry in fs::read_dir(get_base_folder()?)? {
|
for entry in fs::read_dir(get_base_folder()?)? {
|
||||||
let path = entry?.path();
|
let path = entry?.path();
|
||||||
if path.extension() == Some(OsStr::new("name")) {
|
if path.extension() == Some(OsStr::new("name")) {
|
||||||
let stem = path.file_stem().map(|stem| stem.to_str()).flatten();
|
let stem = path.file_stem()
|
||||||
if let Some(name) = stem {
|
.and_then(|stem| stem.to_str())
|
||||||
interfaces.push(name.parse()?);
|
.and_then(|name| name.parse::<InterfaceName>().ok())
|
||||||
|
.filter(|iface| open_socket(iface).is_ok());
|
||||||
|
if let Some(iface) = stem {
|
||||||
|
interfaces.push(iface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,26 +267,34 @@ fn get_userspace_implementation() -> String {
|
||||||
.unwrap_or_else(|_| "wireguard-go".to_string())
|
.unwrap_or_else(|_| "wireguard-go".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_userspace_wireguard(iface: &InterfaceName) -> io::Result<Output> {
|
||||||
|
let mut command = Command::new(&get_userspace_implementation());
|
||||||
|
let output = if cfg!(target_os = "linux") {
|
||||||
|
command.args(&[iface.to_string()]).output()?
|
||||||
|
} else {
|
||||||
|
command
|
||||||
|
.env(
|
||||||
|
"WG_TUN_NAME_FILE",
|
||||||
|
&format!("{}/{}.name", VAR_RUN_PATH, iface),
|
||||||
|
)
|
||||||
|
.args(&["utun"])
|
||||||
|
.output()?
|
||||||
|
};
|
||||||
|
if !output.status.success() {
|
||||||
|
Err(io::ErrorKind::AddrNotAvailable.into())
|
||||||
|
} else {
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn apply(builder: &DeviceUpdate, iface: &InterfaceName) -> io::Result<()> {
|
pub fn apply(builder: &DeviceUpdate, iface: &InterfaceName) -> io::Result<()> {
|
||||||
// If we can't open a configuration socket to an existing interface, try starting it.
|
// If we can't open a configuration socket to an existing interface, try starting it.
|
||||||
let mut sock = match open_socket(iface) {
|
let mut sock = match open_socket(iface) {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
fs::create_dir_all(VAR_RUN_PATH)?;
|
fs::create_dir_all(VAR_RUN_PATH)?;
|
||||||
let mut command = Command::new(&get_userspace_implementation());
|
// Clear out any old namefiles if they didn't lead to a connected socket.
|
||||||
let output = if cfg!(target_os = "linux") {
|
let _ = fs::remove_file(get_namefile(iface)?);
|
||||||
command.args(&[iface.to_string()]).output()?
|
start_userspace_wireguard(iface)?;
|
||||||
} else {
|
|
||||||
command
|
|
||||||
.env(
|
|
||||||
"WG_TUN_NAME_FILE",
|
|
||||||
&format!("{}/{}.name", VAR_RUN_PATH, iface),
|
|
||||||
)
|
|
||||||
.args(&["utun"])
|
|
||||||
.output()?
|
|
||||||
};
|
|
||||||
if !output.status.success() {
|
|
||||||
return Err(io::ErrorKind::AddrNotAvailable.into());
|
|
||||||
}
|
|
||||||
std::thread::sleep(Duration::from_millis(100));
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
open_socket(iface)
|
open_socket(iface)
|
||||||
.map_err(|e| io::Error::new(e.kind(), format!("failed to open socket ({})", e)))?
|
.map_err(|e| io::Error::new(e.kind(), format!("failed to open socket ({})", e)))?
|
||||||
|
|
Loading…
Reference in New Issue