client, wgctrl: fix various linux userspace issues

Fixes #75
pull/74/head
Jake McGinty 2021-05-20 03:16:19 +09:00
parent e95d79db66
commit 5b744d1f78
4 changed files with 47 additions and 14 deletions

View File

@ -253,6 +253,7 @@ fn install(
let iface = iface.parse()?;
redeem_invite(&iface, config, target_conf, network).map_err(|e| {
println!("{} failed to start the interface: {}.", "[!]".red(), e);
println!("{} bringing down the interface.", "[*]".dimmed());
if let Err(e) = wg::down(&iface, network.backend) {
println!("{} failed to bring down interface: {}.", "[*]".yellow(), e.to_string());
@ -263,10 +264,11 @@ fn install(
let mut fetch_success = false;
for _ in 0..3 {
if fetch(&iface, false, hosts_file.clone(), network).is_ok() {
if fetch(&iface, true, hosts_file.clone(), network).is_ok() {
fetch_success = true;
break;
}
thread::sleep(Duration::from_secs(1));
}
if !fetch_success {
println!(

View File

@ -380,8 +380,11 @@ fn spawn_expired_invite_sweeper(db: Db) {
loop {
interval.tick().await;
match DatabasePeer::delete_expired_invites(&db.lock()) {
Ok(deleted) => log::info!("Deleted {} expired peer invitations.", deleted),
Ok(deleted) if deleted > 0 => {
log::info!("Deleted {} expired peer invitations.", deleted)
},
Err(e) => log::error!("Failed to delete expired peer invitations: {}", e),
_ => {},
}
}
});
@ -439,6 +442,7 @@ async fn serve(
let context = context.clone();
async move {
Ok::<_, http::Error>(hyper::service::service_fn(move |req: Request<Body>| {
log::debug!("{} - {} {}", &remote_addr, req.method(), req.uri());
hyper_service(req, context.clone(), remote_addr)
}))
}

View File

@ -8,6 +8,16 @@ use wgctrl::{Backend, Device, DeviceUpdate, InterfaceName, PeerConfigBuilder};
fn cmd(bin: &str, args: &[&str]) -> Result<process::Output, Error> {
let output = Command::new(bin).args(args).output()?;
log::debug!("{} {}", bin, args.join(" "));
log::debug!("status code {:?}", output.status.code());
log::trace!(
"stdout: {}",
String::from_utf8_lossy(&output.stdout)
);
log::trace!(
"stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
if output.status.success() {
Ok(output)
} else {
@ -87,6 +97,7 @@ pub fn up(
if !network.no_routing {
add_route(interface, address)?;
}
cmd("ip", &["link"])?;
Ok(())
}
@ -107,7 +118,10 @@ pub fn set_listen_port(
}
pub fn down(interface: &InterfaceName, backend: Backend) -> Result<(), Error> {
Ok(Device::get(interface, backend)?.delete()?)
Ok(Device::get(interface, backend)
.with_str(interface.as_str_lossy())?
.delete()
.with_str(interface.as_str_lossy())?)
}
/// Add a route in the OS's routing table to get traffic flowing through this interface.
@ -145,7 +159,7 @@ pub fn add_route(interface: &InterfaceName, cidr: IpNetwork) -> Result<bool, Err
&[
"route",
"add",
&cidr.to_string(),
&IpNetwork::new(cidr.network(), cidr.prefix())?.to_string(),
"dev",
&interface.to_string(),
],

View File

@ -33,7 +33,11 @@ fn get_namefile(name: &InterfaceName) -> io::Result<PathBuf> {
}
fn get_socketfile(name: &InterfaceName) -> io::Result<PathBuf> {
if cfg!(target_os = "linux") {
Ok(get_base_folder()?.join(&format!("{}.sock", name)))
} else {
Ok(get_base_folder()?.join(&format!("{}.sock", resolve_tun(name)?)))
}
}
fn open_socket(name: &InterfaceName) -> io::Result<UnixStream> {
@ -42,7 +46,10 @@ fn open_socket(name: &InterfaceName) -> io::Result<UnixStream> {
pub fn resolve_tun(name: &InterfaceName) -> io::Result<String> {
let namefile = get_namefile(name)?;
Ok(fs::read_to_string(namefile)?.trim().to_string())
Ok(fs::read_to_string(namefile)
.map_err(|_| io::Error::new(io::ErrorKind::NotFound, "WireGuard name file can't be read"))?
.trim()
.to_string())
}
pub fn delete_interface(name: &InterfaceName) -> io::Result<()> {
@ -269,18 +276,24 @@ pub fn apply(builder: &DeviceUpdate, iface: &InterfaceName) -> io::Result<()> {
let mut sock = match open_socket(iface) {
Err(_) => {
fs::create_dir_all(VAR_RUN_PATH)?;
let output = Command::new(&get_userspace_implementation())
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()?;
.output()?
};
if !output.status.success() {
return Err(io::ErrorKind::AddrNotAvailable.into());
}
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)))?
},
Ok(sock) => sock,
};