client: enable IPv6 NAT candidate reporting (#192)

pull/194/head
Jake McGinty 2022-02-01 12:21:31 +09:00 committed by GitHub
parent 55222fa3b6
commit 110bace5c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 5 deletions

View File

@ -602,10 +602,13 @@ fn fetch(
.map(|addr| SocketAddr::from((addr, device.listen_port.unwrap_or(51820))).into()) .map(|addr| SocketAddr::from((addr, device.listen_port.unwrap_or(51820))).into())
.collect::<Vec<Endpoint>>(); .collect::<Vec<Endpoint>>();
log::info!( log::info!(
"reporting {} interface address{} as NAT traversal candidates...", "reporting {} interface address{} as NAT traversal candidates",
candidates.len(), 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) { match api.http_form::<_, ()>("PUT", "/user/candidates", &candidates) {
Err(ureq::Error::Status(404, _)) => { 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.") log::warn!("your network is using an old version of innernet-server that doesn't support NAT traversal candidate reporting.")

View File

@ -2,6 +2,7 @@ pub use anyhow::Error;
use std::{ use std::{
fs::{self, File, Permissions}, fs::{self, File, Permissions},
io, io,
net::{IpAddr, Ipv6Addr},
os::unix::fs::PermissionsExt, os::unix::fs::PermissionsExt,
path::Path, path::Path,
time::Duration, time::Duration,
@ -86,7 +87,7 @@ pub fn _get_local_addrs() -> Result<impl Iterator<Item = std::net::IpAddr>, io::
) )
}) })
.filter_map(|addr| match addr.address { .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, _ => None,
}); });
@ -97,5 +98,21 @@ pub fn _get_local_addrs() -> Result<impl Iterator<Item = std::net::IpAddr>, io::
pub use netlink::get_local_addrs as _get_local_addrs; pub use netlink::get_local_addrs as _get_local_addrs;
pub fn get_local_addrs() -> Result<impl Iterator<Item = std::net::IpAddr>, io::Error> { pub fn get_local_addrs() -> Result<impl Iterator<Item = std::net::IpAddr>, 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))
} }

View File

@ -159,7 +159,10 @@ pub fn get_local_addrs() -> Result<impl Iterator<Item = IpAddr>, io::Error> {
None None
}) })
// Only select addresses for helpful links // 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 { .filter_map(|nlas| nlas.iter().find_map(|nla| match nla {
address::nlas::Nla::Address(name) if name.len() == 4 => { address::nlas::Nla::Address(name) if name.len() == 4 => {
let mut addr = [0u8; 4]; let mut addr = [0u8; 4];