diff --git a/client/src/main.rs b/client/src/main.rs index fd6fef9..b20bdb5 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -602,10 +602,13 @@ fn fetch( .map(|addr| SocketAddr::from((addr, device.listen_port.unwrap_or(51820))).into()) .collect::>(); log::info!( - "reporting {} interface address{} as NAT traversal candidates...", + "reporting {} interface address{} as NAT traversal candidates", candidates.len(), - if candidates.len() == 1 { "" } else { "es" } + if candidates.len() == 1 { "" } else { "es" }, ); + for candidate in &candidates { + log::debug!(" candidate: {}", candidate); + } match api.http_form::<_, ()>("PUT", "/user/candidates", &candidates) { Err(ureq::Error::Status(404, _)) => { log::warn!("your network is using an old version of innernet-server that doesn't support NAT traversal candidate reporting.") diff --git a/shared/src/lib.rs b/shared/src/lib.rs index 7df2937..bddef99 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -2,6 +2,7 @@ pub use anyhow::Error; use std::{ fs::{self, File, Permissions}, io, + net::{IpAddr, Ipv6Addr}, os::unix::fs::PermissionsExt, path::Path, time::Duration, @@ -86,7 +87,7 @@ pub fn _get_local_addrs() -> Result, io:: ) }) .filter_map(|addr| match addr.address { - Some(SockAddr::Inet(addr)) if addr.to_std().is_ipv4() => Some(addr.to_std().ip()), + Some(SockAddr::Inet(addr)) => Some(addr.to_std().ip()), _ => None, }); @@ -97,5 +98,21 @@ pub fn _get_local_addrs() -> Result, io:: pub use netlink::get_local_addrs as _get_local_addrs; pub fn get_local_addrs() -> Result, io::Error> { - Ok(_get_local_addrs()?.take(10)) + // TODO(jake): this is temporary pending the stabilization of rust-lang/rust#27709 + fn is_unicast_global(ip: &Ipv6Addr) -> bool { + !((ip.segments()[0] & 0xff00) == 0xff00 // multicast + || ip.is_loopback() + || ip.is_unspecified() + || ((ip.segments()[0] == 0x2001) && (ip.segments()[1] == 0xdb8)) // documentation + || (ip.segments()[0] & 0xffc0) == 0xfe80 // unicast link local + || (ip.segments()[0] & 0xfe00) == 0xfc00) // unicast local + } + + Ok(_get_local_addrs()? + .filter(|ip| { + ip.is_ipv4() + || matches!(ip, + IpAddr::V6(v6) if is_unicast_global(v6)) + }) + .take(10)) } diff --git a/shared/src/netlink.rs b/shared/src/netlink.rs index bb97880..f887db5 100644 --- a/shared/src/netlink.rs +++ b/shared/src/netlink.rs @@ -159,7 +159,10 @@ pub fn get_local_addrs() -> Result, io::Error> { None }) // Only select addresses for helpful links - .filter(move |nlas| nlas.iter().any(|nla| matches!(nla, address::nlas::Nla::Label(label) if links.contains(label)))) + .filter(move |nlas| nlas.iter().any(|nla| { + matches!(nla, address::nlas::Nla::Label(label) if links.contains(label)) + || matches!(nla, address::nlas::Nla::Address(name) if name.len() == 16) + })) .filter_map(|nlas| nlas.iter().find_map(|nla| match nla { address::nlas::Nla::Address(name) if name.len() == 4 => { let mut addr = [0u8; 4];