mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-10-01 01:26:08 -04:00
Merge branch 'android-debugging' into 'main'
Android debugging See merge request veilid/veilid!225
This commit is contained in:
commit
3797442456
26
Cargo.lock
generated
26
Cargo.lock
generated
@ -499,14 +499,13 @@ checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "attohttpc"
|
name = "attohttpc"
|
||||||
version = "0.16.3"
|
version = "0.24.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fdb8867f378f33f78a811a8eb9bf108ad99430d7aad43315dd9319c827ef6247"
|
checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"log",
|
"log",
|
||||||
"url",
|
"url",
|
||||||
"wildmatch",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5290,8 +5289,8 @@ dependencies = [
|
|||||||
"flume",
|
"flume",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
"glob",
|
||||||
"hex",
|
"hex",
|
||||||
"ifstructs",
|
|
||||||
"jni",
|
"jni",
|
||||||
"jni-sys",
|
"jni-sys",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@ -5306,8 +5305,6 @@ dependencies = [
|
|||||||
"lz4_flex",
|
"lz4_flex",
|
||||||
"ndk",
|
"ndk",
|
||||||
"ndk-glue",
|
"ndk-glue",
|
||||||
"netlink-packet-route",
|
|
||||||
"netlink-sys",
|
|
||||||
"nix 0.27.1",
|
"nix 0.27.1",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@ -5316,7 +5313,6 @@ dependencies = [
|
|||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
"paste",
|
"paste",
|
||||||
"range-set-blaze",
|
"range-set-blaze",
|
||||||
"rtnetlink",
|
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile",
|
||||||
"schemars",
|
"schemars",
|
||||||
@ -5380,6 +5376,7 @@ dependencies = [
|
|||||||
"opentelemetry",
|
"opentelemetry",
|
||||||
"opentelemetry-otlp",
|
"opentelemetry-otlp",
|
||||||
"opentelemetry-semantic-conventions",
|
"opentelemetry-semantic-conventions",
|
||||||
|
"paranoid-android",
|
||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -5404,9 +5401,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "veilid-igd"
|
name = "veilid-igd"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28428a3f826ed334f995522e554d7c8c1a5a0e0a0248fc795a31022ddf436c9d"
|
checksum = "ce2b3c073da0025538ff4cf5bea61a7a7a046c1bf060e2d0981c71800747551d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"attohttpc",
|
"attohttpc",
|
||||||
"log",
|
"log",
|
||||||
@ -5482,6 +5479,7 @@ dependencies = [
|
|||||||
"fn_name",
|
"fn_name",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
"ifstructs",
|
||||||
"jni",
|
"jni",
|
||||||
"jni-sys",
|
"jni-sys",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@ -5490,6 +5488,8 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"ndk",
|
"ndk",
|
||||||
"ndk-glue",
|
"ndk-glue",
|
||||||
|
"netlink-packet-route",
|
||||||
|
"netlink-sys",
|
||||||
"nix 0.27.1",
|
"nix 0.27.1",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"oslog",
|
"oslog",
|
||||||
@ -5498,6 +5498,7 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"range-set-blaze",
|
"range-set-blaze",
|
||||||
|
"rtnetlink",
|
||||||
"send_wrapper 0.6.0",
|
"send_wrapper 0.6.0",
|
||||||
"serial_test",
|
"serial_test",
|
||||||
"simplelog",
|
"simplelog",
|
||||||
@ -5515,6 +5516,7 @@ dependencies = [
|
|||||||
"wasm-bindgen-test",
|
"wasm-bindgen-test",
|
||||||
"wasm-logger",
|
"wasm-logger",
|
||||||
"wee_alloc",
|
"wee_alloc",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5779,12 +5781,6 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8"
|
checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wildmatch"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f44b95f62d34113cf558c93511ac93027e03e9c29a60dd0fd70e6e025c7270a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -18,6 +18,7 @@ cursive_core = { git = "https://gitlab.com/veilid/cursive.git" }
|
|||||||
# keyvaluedb-memorydb = { path = "../keyvaluedb/keyvaluedb-memorydb" }
|
# keyvaluedb-memorydb = { path = "../keyvaluedb/keyvaluedb-memorydb" }
|
||||||
# keyvaluedb-sqlite = { path = "../keyvaluedb/keyvaluedb-sqlite" }
|
# keyvaluedb-sqlite = { path = "../keyvaluedb/keyvaluedb-sqlite" }
|
||||||
# keyvaluedb-web = { path = "../keyvaluedb/keyvaluedb-web" }
|
# keyvaluedb-web = { path = "../keyvaluedb/keyvaluedb-web" }
|
||||||
|
# igd = { package = "veilid-igd", path = "../rust-igd" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
|
@ -25,7 +25,6 @@ rt-async-std = [
|
|||||||
"async-std-resolver",
|
"async-std-resolver",
|
||||||
"trust-dns-resolver",
|
"trust-dns-resolver",
|
||||||
"async_executors/async_std",
|
"async_executors/async_std",
|
||||||
"rtnetlink/smol_socket",
|
|
||||||
"veilid-tools/rt-async-std",
|
"veilid-tools/rt-async-std",
|
||||||
]
|
]
|
||||||
rt-tokio = [
|
rt-tokio = [
|
||||||
@ -36,7 +35,6 @@ rt-tokio = [
|
|||||||
"async_executors/tokio_tp",
|
"async_executors/tokio_tp",
|
||||||
"async_executors/tokio_io",
|
"async_executors/tokio_io",
|
||||||
"async_executors/tokio_timer",
|
"async_executors/tokio_timer",
|
||||||
"rtnetlink/tokio_socket",
|
|
||||||
"veilid-tools/rt-tokio",
|
"veilid-tools/rt-tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -170,7 +168,7 @@ keyvaluedb-sqlite = "0.1.1"
|
|||||||
|
|
||||||
# Network
|
# Network
|
||||||
async-tungstenite = { version = "0.23.0", features = ["async-tls"] }
|
async-tungstenite = { version = "0.23.0", features = ["async-tls"] }
|
||||||
igd = { package = "veilid-igd", version = "0.1.0" }
|
igd = { package = "veilid-igd", version = "0.1.1" }
|
||||||
async-tls = "0.12.0"
|
async-tls = "0.12.0"
|
||||||
webpki = "0.22.1"
|
webpki = "0.22.1"
|
||||||
webpki-roots = "0.25.2"
|
webpki-roots = "0.25.2"
|
||||||
@ -238,16 +236,6 @@ ndk = { version = "0.7.0" }
|
|||||||
ndk-glue = { version = "0.7.0", features = ["logger"] }
|
ndk-glue = { version = "0.7.0", features = ["logger"] }
|
||||||
paranoid-android = { version = "0.2.1", optional = true }
|
paranoid-android = { version = "0.2.1", optional = true }
|
||||||
|
|
||||||
# Dependenices for all Unix (Linux, Android, MacOS, iOS)
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
|
||||||
ifstructs = "0.1.1"
|
|
||||||
|
|
||||||
# Dependencies for Linux or Android
|
|
||||||
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies]
|
|
||||||
rtnetlink = { version = "=0.13.1", default-features = false }
|
|
||||||
netlink-sys = { version = "=0.8.5" }
|
|
||||||
netlink-packet-route = { version = "=0.17.1" }
|
|
||||||
|
|
||||||
# Dependencies for Windows
|
# Dependencies for Windows
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { version = "0.3.9", features = ["iptypes", "iphlpapi"] }
|
winapi = { version = "0.3.9", features = ["iptypes", "iphlpapi"] }
|
||||||
@ -279,6 +267,7 @@ wasm-logger = "0.2.0"
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
capnpc = "0.18.0"
|
capnpc = "0.18.0"
|
||||||
|
glob = "0.3.1"
|
||||||
|
|
||||||
[package.metadata.wasm-pack.profile.release]
|
[package.metadata.wasm-pack.profile.release]
|
||||||
wasm-opt = ["-O", "--enable-mutable-globals"]
|
wasm-opt = ["-O", "--enable-mutable-globals"]
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
use std::process::{Command, Stdio};
|
use glob::glob;
|
||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
process::{Command, Stdio},
|
||||||
|
};
|
||||||
|
|
||||||
const CAPNP_VERSION: &str = "1.0.1"; // Keep in sync with scripts/install_capnp.sh
|
const CAPNP_VERSION: &str = "1.0.1"; // Keep in sync with scripts/install_capnp.sh
|
||||||
const PROTOC_VERSION: &str = "24.3"; // Keep in sync with scripts/install_protoc.sh
|
const PROTOC_VERSION: &str = "24.3"; // Keep in sync with scripts/install_protoc.sh
|
||||||
@ -111,4 +115,25 @@ fn main() {
|
|||||||
.run()
|
.run()
|
||||||
.expect("compiling schema");
|
.expect("compiling schema");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix for missing __extenddftf2 on Android x86_64 Emulator
|
||||||
|
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||||
|
// if target_os == "android" || target_os == "linux" {
|
||||||
|
// println!("cargo:rustc-link-lib=stdc++");
|
||||||
|
// } else {
|
||||||
|
// println!("cargo:rustc-link-lib=c++");
|
||||||
|
// }
|
||||||
|
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||||
|
if target_arch == "x86_64" && target_os == "android" {
|
||||||
|
let missing_library = "clang_rt.builtins-x86_64-android";
|
||||||
|
let android_ndk_home = env::var("ANDROID_NDK_HOME").expect("ANDROID_NDK_HOME not set");
|
||||||
|
let lib_path = glob(&format!("{android_ndk_home}/**/lib{missing_library}.a"))
|
||||||
|
.expect("failed to glob")
|
||||||
|
.next()
|
||||||
|
.expect("Need libclang_rt.builtins-x86_64-android.a")
|
||||||
|
.unwrap();
|
||||||
|
let lib_dir = lib_path.parent().unwrap();
|
||||||
|
println!("cargo:rustc-link-search={}", lib_dir.display());
|
||||||
|
println!("cargo:rustc-link-lib=static={missing_library}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,5 @@ pub use system::*;
|
|||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
pub mod android;
|
pub mod android;
|
||||||
pub mod network_interfaces;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -48,11 +48,19 @@ impl ProtectedStore {
|
|||||||
// Attempt to open the secure keyring
|
// Attempt to open the secure keyring
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(target_os = "android")] {
|
if #[cfg(target_os = "android")] {
|
||||||
inner.keyring_manager = KeyringManager::new_secure(&c.program_name, crate::intf::android::get_android_globals()).ok();
|
let maybe_km = KeyringManager::new_secure(&c.program_name, crate::intf::android::get_android_globals());
|
||||||
} else {
|
} else {
|
||||||
inner.keyring_manager = KeyringManager::new_secure(&c.program_name).ok();
|
let maybe_km = KeyringManager::new_secure(&c.program_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner.keyring_manager = match maybe_km {
|
||||||
|
Ok(v) => Some(v),
|
||||||
|
Err(e) => {
|
||||||
|
log_pstore!(error "Failed to create secure keyring manager: {}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (c.protected_store.always_use_insecure_storage
|
if (c.protected_store.always_use_insecure_storage
|
||||||
|| c.protected_store.allow_insecure_fallback)
|
|| c.protected_store.allow_insecure_fallback)
|
||||||
@ -78,6 +86,7 @@ impl ProtectedStore {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if inner.keyring_manager.is_none() {
|
if inner.keyring_manager.is_none() {
|
||||||
|
log_pstore!(error "QWERQWER");
|
||||||
bail!("Could not initialize the protected store.");
|
bail!("Could not initialize the protected store.");
|
||||||
}
|
}
|
||||||
c.protected_store.delete
|
c.protected_store.delete
|
||||||
|
@ -39,8 +39,11 @@ struct DiscoveryContextInner {
|
|||||||
struct DiscoveryContextUnlockedInner {
|
struct DiscoveryContextUnlockedInner {
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
net: Network,
|
net: Network,
|
||||||
|
clear_network_callback: ClearNetworkCallback,
|
||||||
|
|
||||||
// per-protocol
|
// per-protocol
|
||||||
intf_addrs: Vec<SocketAddress>,
|
intf_addrs: Vec<SocketAddress>,
|
||||||
|
existing_external_address: Option<SocketAddress>,
|
||||||
protocol_type: ProtocolType,
|
protocol_type: ProtocolType,
|
||||||
address_type: AddressType,
|
address_type: AddressType,
|
||||||
}
|
}
|
||||||
@ -51,21 +54,45 @@ pub struct DiscoveryContext {
|
|||||||
inner: Arc<Mutex<DiscoveryContextInner>>,
|
inner: Arc<Mutex<DiscoveryContextInner>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type ClearNetworkCallback = Arc<dyn Fn() -> SendPinBoxFuture<()> + Send + Sync>;
|
||||||
|
|
||||||
impl DiscoveryContext {
|
impl DiscoveryContext {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
net: Network,
|
net: Network,
|
||||||
protocol_type: ProtocolType,
|
protocol_type: ProtocolType,
|
||||||
address_type: AddressType,
|
address_type: AddressType,
|
||||||
|
clear_network_callback: ClearNetworkCallback,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let intf_addrs =
|
let intf_addrs =
|
||||||
Self::get_local_addresses(routing_table.clone(), protocol_type, address_type);
|
Self::get_local_addresses(routing_table.clone(), protocol_type, address_type);
|
||||||
|
|
||||||
|
// Get the existing external address to check to see if it has changed
|
||||||
|
let existing_dial_info = routing_table.all_filtered_dial_info_details(
|
||||||
|
RoutingDomain::PublicInternet.into(),
|
||||||
|
&DialInfoFilter::default()
|
||||||
|
.with_address_type(address_type)
|
||||||
|
.with_protocol_type(protocol_type),
|
||||||
|
);
|
||||||
|
let existing_external_address = if existing_dial_info.len() == 1 {
|
||||||
|
Some(
|
||||||
|
existing_dial_info
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
|
.dial_info
|
||||||
|
.socket_address(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
unlocked_inner: Arc::new(DiscoveryContextUnlockedInner {
|
unlocked_inner: Arc::new(DiscoveryContextUnlockedInner {
|
||||||
routing_table,
|
routing_table,
|
||||||
net,
|
net,
|
||||||
|
clear_network_callback,
|
||||||
intf_addrs,
|
intf_addrs,
|
||||||
|
existing_external_address,
|
||||||
protocol_type,
|
protocol_type,
|
||||||
address_type,
|
address_type,
|
||||||
}),
|
}),
|
||||||
@ -631,6 +658,30 @@ impl DiscoveryContext {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Did external address change from the last time we made dialinfo?
|
||||||
|
// Disregard port for this because we only need to know if the ip address has changed
|
||||||
|
// If the port has changed it will change only for this protocol and will be overwritten individually by each protocol discover()
|
||||||
|
let some_clear_network_callback = {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
let ext_1 = inner.external_1.as_ref().unwrap().address.address();
|
||||||
|
let ext_2 = inner.external_2.as_ref().unwrap().address.address();
|
||||||
|
if (ext_1 != ext_2)
|
||||||
|
|| Some(ext_1)
|
||||||
|
!= self
|
||||||
|
.unlocked_inner
|
||||||
|
.existing_external_address
|
||||||
|
.map(|ea| ea.address())
|
||||||
|
{
|
||||||
|
// External address was not found, or has changed, go ahead and clear the network so we can do better
|
||||||
|
Some(self.unlocked_inner.clear_network_callback.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(clear_network_callback) = some_clear_network_callback {
|
||||||
|
clear_network_callback().await;
|
||||||
|
}
|
||||||
|
|
||||||
// UPNP Automatic Mapping
|
// UPNP Automatic Mapping
|
||||||
///////////
|
///////////
|
||||||
if enable_upnp {
|
if enable_upnp {
|
||||||
|
@ -26,7 +26,7 @@ struct PortMapValue {
|
|||||||
|
|
||||||
struct IGDManagerInner {
|
struct IGDManagerInner {
|
||||||
local_ip_addrs: BTreeMap<AddressType, IpAddr>,
|
local_ip_addrs: BTreeMap<AddressType, IpAddr>,
|
||||||
gateways: BTreeMap<AddressType, Arc<Gateway>>,
|
gateways: BTreeMap<IpAddr, Arc<Gateway>>,
|
||||||
port_maps: BTreeMap<PortMapKey, PortMapValue>,
|
port_maps: BTreeMap<PortMapKey, PortMapValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,17 +121,21 @@ impl IGDManager {
|
|||||||
|
|
||||||
fn find_gateway(
|
fn find_gateway(
|
||||||
inner: &mut IGDManagerInner,
|
inner: &mut IGDManagerInner,
|
||||||
address_type: AddressType,
|
local_ip: IpAddr,
|
||||||
) -> Option<Arc<Gateway>> {
|
) -> Option<Arc<Gateway>> {
|
||||||
if let Some(gw) = inner.gateways.get(&address_type) {
|
|
||||||
|
if let Some(gw) = inner.gateways.get(&local_ip) {
|
||||||
return Some(gw.clone());
|
return Some(gw.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let gateway = match address_type {
|
let gateway = match local_ip {
|
||||||
AddressType::IPV4 => {
|
IpAddr::V4(v4) => {
|
||||||
match igd::search_gateway(SearchOptions::new_v4(
|
let mut opts = SearchOptions::new_v4(
|
||||||
UPNP_GATEWAY_DETECT_TIMEOUT_MS as u64,
|
UPNP_GATEWAY_DETECT_TIMEOUT_MS as u64,
|
||||||
)) {
|
);
|
||||||
|
opts.bind_addr = SocketAddr::V4(SocketAddrV4::new(v4, 0));
|
||||||
|
|
||||||
|
match igd::search_gateway(opts) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log_net!(debug "couldn't find ipv4 igd: {}", e);
|
log_net!(debug "couldn't find ipv4 igd: {}", e);
|
||||||
@ -139,11 +143,14 @@ impl IGDManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddressType::IPV6 => {
|
IpAddr::V6(v6) => {
|
||||||
match igd::search_gateway(SearchOptions::new_v6(
|
let mut opts = SearchOptions::new_v6(
|
||||||
Ipv6SearchScope::LinkLocal,
|
Ipv6SearchScope::LinkLocal,
|
||||||
UPNP_GATEWAY_DETECT_TIMEOUT_MS as u64,
|
UPNP_GATEWAY_DETECT_TIMEOUT_MS as u64,
|
||||||
)) {
|
);
|
||||||
|
opts.bind_addr = SocketAddr::V6(SocketAddrV6::new(v6, 0, 0, 0));
|
||||||
|
|
||||||
|
match igd::search_gateway(opts) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log_net!(debug "couldn't find ipv6 igd: {}", e);
|
log_net!(debug "couldn't find ipv6 igd: {}", e);
|
||||||
@ -151,17 +158,18 @@ impl IGDManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
let gw = Arc::new(gateway);
|
let gw = Arc::new(gateway);
|
||||||
inner.gateways.insert(address_type, gw.clone());
|
inner.gateways.insert(local_ip, gw.clone());
|
||||||
Some(gw)
|
Some(gw)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_gateway(
|
fn get_gateway(
|
||||||
inner: &mut IGDManagerInner,
|
inner: &mut IGDManagerInner,
|
||||||
address_type: AddressType,
|
local_ip: IpAddr,
|
||||||
) -> Option<Arc<Gateway>> {
|
) -> Option<Arc<Gateway>> {
|
||||||
if let Some(gw) = inner.gateways.get(&address_type) {
|
if let Some(gw) = inner.gateways.get(&local_ip) {
|
||||||
return Some(gw.clone());
|
return Some(gw.clone());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -191,8 +199,12 @@ impl IGDManager {
|
|||||||
let pmk = found?;
|
let pmk = found?;
|
||||||
let _pmv = inner.port_maps.remove(&pmk).expect("key found but remove failed");
|
let _pmv = inner.port_maps.remove(&pmk).expect("key found but remove failed");
|
||||||
|
|
||||||
|
|
||||||
|
// Get local ip address
|
||||||
|
let local_ip = Self::find_local_ip(&mut inner, at)?;
|
||||||
|
|
||||||
// Find gateway
|
// Find gateway
|
||||||
let gw = Self::find_gateway(&mut inner, at)?;
|
let gw = Self::find_gateway(&mut inner, local_ip)?;
|
||||||
|
|
||||||
// Unmap port
|
// Unmap port
|
||||||
match gw.remove_port(convert_llpt(llpt), mapped_port) {
|
match gw.remove_port(convert_llpt(llpt), mapped_port) {
|
||||||
@ -233,7 +245,7 @@ impl IGDManager {
|
|||||||
let local_ip = Self::find_local_ip(&mut inner, at)?;
|
let local_ip = Self::find_local_ip(&mut inner, at)?;
|
||||||
|
|
||||||
// Find gateway
|
// Find gateway
|
||||||
let gw = Self::find_gateway(&mut inner, at)?;
|
let gw = Self::find_gateway(&mut inner, local_ip)?;
|
||||||
|
|
||||||
// Get external address
|
// Get external address
|
||||||
let ext_ip = match gw.get_external_ip() {
|
let ext_ip = match gw.get_external_ip() {
|
||||||
@ -326,14 +338,6 @@ impl IGDManager {
|
|||||||
// Process full renewals
|
// Process full renewals
|
||||||
for (k, v) in full_renews {
|
for (k, v) in full_renews {
|
||||||
|
|
||||||
// Get gateway for address type
|
|
||||||
let gw = match Self::get_gateway(&mut inner, k.at) {
|
|
||||||
Some(gw) => gw,
|
|
||||||
None => {
|
|
||||||
return Err(eyre!("gateway missing for address type"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get local ip for address type
|
// Get local ip for address type
|
||||||
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
|
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
|
||||||
Some(ip) => ip,
|
Some(ip) => ip,
|
||||||
@ -342,6 +346,14 @@ impl IGDManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get gateway for interface
|
||||||
|
let gw = match Self::get_gateway(&mut inner, local_ip) {
|
||||||
|
Some(gw) => gw,
|
||||||
|
None => {
|
||||||
|
return Err(eyre!("gateway missing for interface"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Delete the mapping if it exists, ignore any errors here
|
// Delete the mapping if it exists, ignore any errors here
|
||||||
let _ = gw.remove_port(convert_llpt(k.llpt), v.mapped_port);
|
let _ = gw.remove_port(convert_llpt(k.llpt), v.mapped_port);
|
||||||
inner.port_maps.remove(&k);
|
inner.port_maps.remove(&k);
|
||||||
@ -370,14 +382,6 @@ impl IGDManager {
|
|||||||
// Process normal renewals
|
// Process normal renewals
|
||||||
for (k, mut v) in renews {
|
for (k, mut v) in renews {
|
||||||
|
|
||||||
// Get gateway for address type
|
|
||||||
let gw = match Self::get_gateway(&mut inner, k.at) {
|
|
||||||
Some(gw) => gw,
|
|
||||||
None => {
|
|
||||||
return Err(eyre!("gateway missing for address type"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get local ip for address type
|
// Get local ip for address type
|
||||||
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
|
let local_ip = match Self::get_local_ip(&mut inner, k.at) {
|
||||||
Some(ip) => ip,
|
Some(ip) => ip,
|
||||||
@ -386,6 +390,14 @@ impl IGDManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get gateway for interface
|
||||||
|
let gw = match Self::get_gateway(&mut inner, local_ip) {
|
||||||
|
Some(gw) => gw,
|
||||||
|
None => {
|
||||||
|
return Err(eyre!("gateway missing for address type"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let desc = this.get_description(k.llpt, k.local_port);
|
let desc = this.get_description(k.llpt, k.local_port);
|
||||||
match gw.add_port(convert_llpt(k.llpt), v.mapped_port, SocketAddr::new(local_ip, k.local_port), (UPNP_MAPPING_LIFETIME_MS + 999) / 1000, &desc) {
|
match gw.add_port(convert_llpt(k.llpt), v.mapped_port, SocketAddr::new(local_ip, k.local_port), (UPNP_MAPPING_LIFETIME_MS + 999) / 1000, &desc) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
|
@ -10,7 +10,6 @@ use super::*;
|
|||||||
use crate::routing_table::*;
|
use crate::routing_table::*;
|
||||||
use connection_manager::*;
|
use connection_manager::*;
|
||||||
use discovery_context::*;
|
use discovery_context::*;
|
||||||
use network_interfaces::*;
|
|
||||||
use network_tcp::*;
|
use network_tcp::*;
|
||||||
use protocol::tcp::RawTcpProtocolHandler;
|
use protocol::tcp::RawTcpProtocolHandler;
|
||||||
use protocol::udp::RawUdpProtocolHandler;
|
use protocol::udp::RawUdpProtocolHandler;
|
||||||
@ -99,6 +98,8 @@ struct NetworkInner {
|
|||||||
enable_ipv6_local: bool,
|
enable_ipv6_local: bool,
|
||||||
/// set if we need to calculate our public dial info again
|
/// set if we need to calculate our public dial info again
|
||||||
needs_public_dial_info_check: bool,
|
needs_public_dial_info_check: bool,
|
||||||
|
/// set if we have yet to clear the network during public dial info checking
|
||||||
|
network_already_cleared: bool,
|
||||||
/// the punishment closure to enax
|
/// the punishment closure to enax
|
||||||
public_dial_info_check_punishment: Option<Box<dyn FnOnce() + Send + 'static>>,
|
public_dial_info_check_punishment: Option<Box<dyn FnOnce() + Send + 'static>>,
|
||||||
/// udp socket record for bound-first sockets, which are used to guarantee a port is available before
|
/// udp socket record for bound-first sockets, which are used to guarantee a port is available before
|
||||||
@ -148,6 +149,7 @@ impl Network {
|
|||||||
network_started: false,
|
network_started: false,
|
||||||
network_needs_restart: false,
|
network_needs_restart: false,
|
||||||
needs_public_dial_info_check: false,
|
needs_public_dial_info_check: false,
|
||||||
|
network_already_cleared: false,
|
||||||
public_dial_info_check_punishment: None,
|
public_dial_info_check_punishment: None,
|
||||||
protocol_config: Default::default(),
|
protocol_config: Default::default(),
|
||||||
static_public_dialinfo: ProtocolTypeSet::empty(),
|
static_public_dialinfo: ProtocolTypeSet::empty(),
|
||||||
@ -313,7 +315,7 @@ impl Network {
|
|||||||
if !from.ip().is_unspecified() {
|
if !from.ip().is_unspecified() {
|
||||||
vec![*from]
|
vec![*from]
|
||||||
} else {
|
} else {
|
||||||
let addrs = self.get_usable_interface_addresses();
|
let addrs = self.get_stable_interface_addresses();
|
||||||
addrs
|
addrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|a| {
|
.filter_map(|a| {
|
||||||
@ -355,13 +357,13 @@ impl Network {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_usable_interface_address(&self, addr: IpAddr) -> bool {
|
pub fn is_stable_interface_address(&self, addr: IpAddr) -> bool {
|
||||||
let usable_addrs = self.get_usable_interface_addresses();
|
let stable_addrs = self.get_stable_interface_addresses();
|
||||||
usable_addrs.contains(&addr)
|
stable_addrs.contains(&addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_usable_interface_addresses(&self) -> Vec<IpAddr> {
|
pub fn get_stable_interface_addresses(&self) -> Vec<IpAddr> {
|
||||||
let addrs = self.unlocked_inner.interfaces.best_addresses();
|
let addrs = self.unlocked_inner.interfaces.stable_addresses();
|
||||||
let addrs: Vec<IpAddr> = addrs
|
let addrs: Vec<IpAddr> = addrs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|addr| {
|
.filter(|addr| {
|
||||||
@ -372,15 +374,20 @@ impl Network {
|
|||||||
addrs
|
addrs
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if our interface addresses have changed, if so we need to punt the network
|
// See if our interface addresses have changed, if so redo public dial info if necessary
|
||||||
// and redo all our addresses. This is overkill, but anything more accurate
|
|
||||||
// would require inspection of routing tables that we dont want to bother with
|
|
||||||
async fn check_interface_addresses(&self) -> EyreResult<bool> {
|
async fn check_interface_addresses(&self) -> EyreResult<bool> {
|
||||||
if !self.unlocked_inner.interfaces.refresh().await? {
|
if !self
|
||||||
|
.unlocked_inner
|
||||||
|
.interfaces
|
||||||
|
.refresh()
|
||||||
|
.await
|
||||||
|
.wrap_err("failed to check network interfaces")?
|
||||||
|
{
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inner.lock().network_needs_restart = true;
|
self.inner.lock().needs_public_dial_info_check = true;
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,7 +704,7 @@ impl Network {
|
|||||||
self.unlocked_inner
|
self.unlocked_inner
|
||||||
.interfaces
|
.interfaces
|
||||||
.with_interfaces(|interfaces| {
|
.with_interfaces(|interfaces| {
|
||||||
trace!("interfaces: {:#?}", interfaces);
|
debug!("interfaces: {:#?}", interfaces);
|
||||||
|
|
||||||
for intf in interfaces.values() {
|
for intf in interfaces.values() {
|
||||||
// Skip networks that we should never encounter
|
// Skip networks that we should never encounter
|
||||||
@ -721,7 +728,7 @@ impl Network {
|
|||||||
{
|
{
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.enable_ipv4 = false;
|
inner.enable_ipv4 = false;
|
||||||
for addr in self.get_usable_interface_addresses() {
|
for addr in self.get_stable_interface_addresses() {
|
||||||
if addr.is_ipv4() {
|
if addr.is_ipv4() {
|
||||||
log_net!(debug "enable address {:?} as ipv4", addr);
|
log_net!(debug "enable address {:?} as ipv4", addr);
|
||||||
inner.enable_ipv4 = true;
|
inner.enable_ipv4 = true;
|
||||||
@ -975,9 +982,8 @@ impl Network {
|
|||||||
_l: u64,
|
_l: u64,
|
||||||
_t: u64,
|
_t: u64,
|
||||||
) -> EyreResult<()> {
|
) -> EyreResult<()> {
|
||||||
if self.check_interface_addresses().await? {
|
self.check_interface_addresses().await?;
|
||||||
info!("interface addresses changed, restarting network");
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ impl Network {
|
|||||||
|
|
||||||
editor.clear_dial_info_details(None, None);
|
editor.clear_dial_info_details(None, None);
|
||||||
editor.set_network_class(Some(NetworkClass::OutboundOnly));
|
editor.set_network_class(Some(NetworkClass::OutboundOnly));
|
||||||
editor.clear_relay_node();
|
|
||||||
editor.commit(true).await;
|
editor.commit(true).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,13 +50,11 @@ impl Network {
|
|||||||
let mut add = false;
|
let mut add = false;
|
||||||
|
|
||||||
if let Some(edi) = existing_dial_info.get(&(pt, at)) {
|
if let Some(edi) = existing_dial_info.get(&(pt, at)) {
|
||||||
if did.class < edi.class {
|
if did.class <= edi.class {
|
||||||
// Better dial info class was found, clear existing dialinfo for this pt/at pair
|
// Better or same dial info class was found, clear existing dialinfo for this pt/at pair
|
||||||
|
// Only keep one dial info per protocol/address type combination
|
||||||
clear = true;
|
clear = true;
|
||||||
add = true;
|
add = true;
|
||||||
} else if did.class == edi.class {
|
|
||||||
// Same dial info class, just add dial info
|
|
||||||
add = true;
|
|
||||||
}
|
}
|
||||||
// Otherwise, don't upgrade, don't add, this is worse than what we have already
|
// Otherwise, don't upgrade, don't add, this is worse than what we have already
|
||||||
} else {
|
} else {
|
||||||
@ -103,7 +100,7 @@ impl Network {
|
|||||||
) -> EyreResult<()> {
|
) -> EyreResult<()> {
|
||||||
// Figure out if we can optimize TCP/WS checking since they are often on the same port
|
// Figure out if we can optimize TCP/WS checking since they are often on the same port
|
||||||
let (protocol_config, tcp_same_port) = {
|
let (protocol_config, tcp_same_port) = {
|
||||||
let inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
let protocol_config = inner.protocol_config.clone();
|
let protocol_config = inner.protocol_config.clone();
|
||||||
let tcp_same_port = if protocol_config.inbound.contains(ProtocolType::TCP)
|
let tcp_same_port = if protocol_config.inbound.contains(ProtocolType::TCP)
|
||||||
&& protocol_config.inbound.contains(ProtocolType::WS)
|
&& protocol_config.inbound.contains(ProtocolType::WS)
|
||||||
@ -112,6 +109,10 @@ impl Network {
|
|||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
// Allow network to be cleared if external addresses change
|
||||||
|
inner.network_already_cleared = false;
|
||||||
|
|
||||||
|
//
|
||||||
(protocol_config, tcp_same_port)
|
(protocol_config, tcp_same_port)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,8 +126,7 @@ impl Network {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Clear public dialinfo and network class in prep for discovery
|
// Set most permissive network config
|
||||||
|
|
||||||
let mut editor = self
|
let mut editor = self
|
||||||
.routing_table()
|
.routing_table()
|
||||||
.edit_routing_domain(RoutingDomain::PublicInternet);
|
.edit_routing_domain(RoutingDomain::PublicInternet);
|
||||||
@ -136,10 +136,29 @@ impl Network {
|
|||||||
protocol_config.family_global,
|
protocol_config.family_global,
|
||||||
protocol_config.public_internet_capabilities.clone(),
|
protocol_config.public_internet_capabilities.clone(),
|
||||||
);
|
);
|
||||||
|
editor.commit(true).await;
|
||||||
|
|
||||||
|
// Create a callback to clear the network if we need to 'start over'
|
||||||
|
let this = self.clone();
|
||||||
|
let clear_network_callback: ClearNetworkCallback = Arc::new(move || {
|
||||||
|
let this = this.clone();
|
||||||
|
Box::pin(async move {
|
||||||
|
// Ensure we only do this once per network class discovery
|
||||||
|
{
|
||||||
|
let mut inner = this.inner.lock();
|
||||||
|
if inner.network_already_cleared {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inner.network_already_cleared = true;
|
||||||
|
}
|
||||||
|
let mut editor = this
|
||||||
|
.routing_table()
|
||||||
|
.edit_routing_domain(RoutingDomain::PublicInternet);
|
||||||
editor.clear_dial_info_details(None, None);
|
editor.clear_dial_info_details(None, None);
|
||||||
editor.set_network_class(None);
|
editor.set_network_class(None);
|
||||||
editor.clear_relay_node();
|
|
||||||
editor.commit(true).await;
|
editor.commit(true).await;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
// Process all protocol and address combinations
|
// Process all protocol and address combinations
|
||||||
let mut unord = FuturesUnordered::new();
|
let mut unord = FuturesUnordered::new();
|
||||||
@ -152,6 +171,7 @@ impl Network {
|
|||||||
self.clone(),
|
self.clone(),
|
||||||
ProtocolType::UDP,
|
ProtocolType::UDP,
|
||||||
AddressType::IPV4,
|
AddressType::IPV4,
|
||||||
|
clear_network_callback.clone(),
|
||||||
);
|
);
|
||||||
udpv4_context
|
udpv4_context
|
||||||
.discover(&mut unord)
|
.discover(&mut unord)
|
||||||
@ -166,6 +186,7 @@ impl Network {
|
|||||||
self.clone(),
|
self.clone(),
|
||||||
ProtocolType::UDP,
|
ProtocolType::UDP,
|
||||||
AddressType::IPV6,
|
AddressType::IPV6,
|
||||||
|
clear_network_callback.clone(),
|
||||||
);
|
);
|
||||||
udpv6_context
|
udpv6_context
|
||||||
.discover(&mut unord)
|
.discover(&mut unord)
|
||||||
@ -182,6 +203,7 @@ impl Network {
|
|||||||
self.clone(),
|
self.clone(),
|
||||||
ProtocolType::TCP,
|
ProtocolType::TCP,
|
||||||
AddressType::IPV4,
|
AddressType::IPV4,
|
||||||
|
clear_network_callback.clone(),
|
||||||
);
|
);
|
||||||
tcpv4_context
|
tcpv4_context
|
||||||
.discover(&mut unord)
|
.discover(&mut unord)
|
||||||
@ -195,6 +217,7 @@ impl Network {
|
|||||||
self.clone(),
|
self.clone(),
|
||||||
ProtocolType::WS,
|
ProtocolType::WS,
|
||||||
AddressType::IPV4,
|
AddressType::IPV4,
|
||||||
|
clear_network_callback.clone(),
|
||||||
);
|
);
|
||||||
wsv4_context
|
wsv4_context
|
||||||
.discover(&mut unord)
|
.discover(&mut unord)
|
||||||
@ -211,6 +234,7 @@ impl Network {
|
|||||||
self.clone(),
|
self.clone(),
|
||||||
ProtocolType::TCP,
|
ProtocolType::TCP,
|
||||||
AddressType::IPV6,
|
AddressType::IPV6,
|
||||||
|
clear_network_callback.clone(),
|
||||||
);
|
);
|
||||||
tcpv6_context
|
tcpv6_context
|
||||||
.discover(&mut unord)
|
.discover(&mut unord)
|
||||||
@ -225,6 +249,7 @@ impl Network {
|
|||||||
self.clone(),
|
self.clone(),
|
||||||
ProtocolType::WS,
|
ProtocolType::WS,
|
||||||
AddressType::IPV6,
|
AddressType::IPV6,
|
||||||
|
clear_network_callback.clone(),
|
||||||
);
|
);
|
||||||
wsv6_context
|
wsv6_context
|
||||||
.discover(&mut unord)
|
.discover(&mut unord)
|
||||||
|
@ -342,7 +342,7 @@ impl Network {
|
|||||||
|
|
||||||
// See if this public address is also a local interface address we haven't registered yet
|
// See if this public address is also a local interface address we haven't registered yet
|
||||||
let is_interface_address = (|| {
|
let is_interface_address = (|| {
|
||||||
for ip_addr in self.get_usable_interface_addresses() {
|
for ip_addr in self.get_stable_interface_addresses() {
|
||||||
if pdi_addr.ip() == ip_addr {
|
if pdi_addr.ip() == ip_addr {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -438,7 +438,7 @@ impl Network {
|
|||||||
|
|
||||||
// See if this public address is also a local interface address
|
// See if this public address is also a local interface address
|
||||||
if !registered_addresses.contains(&gsa.ip())
|
if !registered_addresses.contains(&gsa.ip())
|
||||||
&& self.is_usable_interface_address(gsa.ip())
|
&& self.is_stable_interface_address(gsa.ip())
|
||||||
{
|
{
|
||||||
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
||||||
}
|
}
|
||||||
@ -552,7 +552,7 @@ impl Network {
|
|||||||
|
|
||||||
// See if this public address is also a local interface address
|
// See if this public address is also a local interface address
|
||||||
if !registered_addresses.contains(&gsa.ip())
|
if !registered_addresses.contains(&gsa.ip())
|
||||||
&& self.is_usable_interface_address(gsa.ip())
|
&& self.is_stable_interface_address(gsa.ip())
|
||||||
{
|
{
|
||||||
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
||||||
}
|
}
|
||||||
@ -653,7 +653,7 @@ impl Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See if this public address is also a local interface address
|
// See if this public address is also a local interface address
|
||||||
if self.is_usable_interface_address(pdi_addr.ip()) {
|
if self.is_stable_interface_address(pdi_addr.ip()) {
|
||||||
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
editor_local_network.register_dial_info(pdi, DialInfoClass::Direct)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,11 +425,11 @@ impl Network {
|
|||||||
trace!("network stopped");
|
trace!("network stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_usable_interface_address(&self, _addr: IpAddr) -> bool {
|
pub fn is_stable_interface_address(&self, _addr: IpAddr) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_usable_interface_addresses(&self) -> Vec<IpAddr> {
|
pub fn get_stable_interface_addresses(&self) -> Vec<IpAddr> {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,6 +384,22 @@ impl RoutingTable {
|
|||||||
let routing_table = self.clone();
|
let routing_table = self.clone();
|
||||||
unord.push(
|
unord.push(
|
||||||
async move {
|
async move {
|
||||||
|
// Get what contact method would be used for contacting the bootstrap
|
||||||
|
let bsdi = match routing_table
|
||||||
|
.network_manager()
|
||||||
|
.get_node_contact_method(nr.clone())
|
||||||
|
{
|
||||||
|
Ok(NodeContactMethod::Direct(v)) => v,
|
||||||
|
Ok(v) => {
|
||||||
|
log_rtab!(warn "invalid contact method for bootstrap: {:?}", v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log_rtab!(warn "unable to bootstrap: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Need VALID signed peer info, so ask bootstrap to find_node of itself
|
// Need VALID signed peer info, so ask bootstrap to find_node of itself
|
||||||
// which will ensure it has the bootstrap's signed peer info as part of the response
|
// which will ensure it has the bootstrap's signed peer info as part of the response
|
||||||
let _ = routing_table.find_target(crypto_kind, nr.clone()).await;
|
let _ = routing_table.find_target(crypto_kind, nr.clone()).await;
|
||||||
@ -391,7 +407,10 @@ impl RoutingTable {
|
|||||||
// Ensure we got the signed peer info
|
// Ensure we got the signed peer info
|
||||||
if !nr.signed_node_info_has_valid_signature(RoutingDomain::PublicInternet) {
|
if !nr.signed_node_info_has_valid_signature(RoutingDomain::PublicInternet) {
|
||||||
log_rtab!(warn "bootstrap server is not responding");
|
log_rtab!(warn "bootstrap server is not responding");
|
||||||
log_rtab!(debug "bootstrap server is not responding: {}", nr);
|
log_rtab!(debug "bootstrap server is not responding for dialinfo: {}", bsdi);
|
||||||
|
|
||||||
|
// Try a different dialinfo next time
|
||||||
|
routing_table.network_manager().address_filter().set_dial_info_failed(bsdi);
|
||||||
} else {
|
} else {
|
||||||
// otherwise this bootstrap is valid, lets ask it to find ourselves now
|
// otherwise this bootstrap is valid, lets ask it to find ourselves now
|
||||||
routing_table.reverse_find_node(crypto_kind, nr, true).await
|
routing_table.reverse_find_node(crypto_kind, nr, true).await
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pub mod test_host_interface;
|
|
||||||
pub mod test_protected_store;
|
pub mod test_protected_store;
|
||||||
pub mod test_veilid_config;
|
pub mod test_veilid_config;
|
||||||
pub mod test_veilid_core;
|
pub mod test_veilid_core;
|
||||||
|
@ -13,8 +13,6 @@ use crate::*;
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn run_all_tests() {
|
pub async fn run_all_tests() {
|
||||||
// iOS and Android tests also run these.
|
// iOS and Android tests also run these.
|
||||||
info!("TEST: test_host_interface");
|
|
||||||
test_host_interface::test_all().await;
|
|
||||||
info!("TEST: test_types");
|
info!("TEST: test_types");
|
||||||
test_types::test_all().await;
|
test_types::test_all().await;
|
||||||
info!("TEST: test_veilid_core");
|
info!("TEST: test_veilid_core");
|
||||||
@ -114,8 +112,6 @@ cfg_if! {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
run_test!(test_host_interface);
|
|
||||||
|
|
||||||
run_test!(test_types);
|
run_test!(test_types);
|
||||||
|
|
||||||
run_test!(test_veilid_core);
|
run_test!(test_veilid_core);
|
||||||
|
@ -2,8 +2,8 @@ import 'dart:async';
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -63,3 +63,4 @@ hostname = "^0"
|
|||||||
# Dependencies for Android builds only
|
# Dependencies for Android builds only
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
jni = "^0"
|
jni = "^0"
|
||||||
|
paranoid-android = "0.2.1"
|
||||||
|
@ -166,6 +166,16 @@ pub extern "C" fn initialize_veilid_core(platform_config: FfiStr) {
|
|||||||
|
|
||||||
// Terminal logger
|
// Terminal logger
|
||||||
if platform_config.logging.terminal.enabled {
|
if platform_config.logging.terminal.enabled {
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(target_os = "android")] {
|
||||||
|
let filter =
|
||||||
|
veilid_core::VeilidLayerFilter::new(platform_config.logging.terminal.level, None);
|
||||||
|
let layer = paranoid_android::layer("veilid-flutter")
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_filter(filter.clone());
|
||||||
|
filters.insert("terminal", filter);
|
||||||
|
layers.push(layer.boxed());
|
||||||
|
} else {
|
||||||
let filter =
|
let filter =
|
||||||
veilid_core::VeilidLayerFilter::new(platform_config.logging.terminal.level, None);
|
veilid_core::VeilidLayerFilter::new(platform_config.logging.terminal.level, None);
|
||||||
let layer = tracing_subscriber::fmt::Layer::new()
|
let layer = tracing_subscriber::fmt::Layer::new()
|
||||||
@ -174,6 +184,8 @@ pub extern "C" fn initialize_veilid_core(platform_config: FfiStr) {
|
|||||||
.with_filter(filter.clone());
|
.with_filter(filter.clone());
|
||||||
filters.insert("terminal", filter);
|
filters.insert("terminal", filter);
|
||||||
layers.push(layer.boxed());
|
layers.push(layer.boxed());
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// OpenTelemetry logger
|
// OpenTelemetry logger
|
||||||
@ -237,6 +249,7 @@ pub extern "C" fn initialize_veilid_core(platform_config: FfiStr) {
|
|||||||
.try_init()
|
.try_init()
|
||||||
.map_err(|e| format!("failed to initialize logging: {}", e))
|
.map_err(|e| format!("failed to initialize logging: {}", e))
|
||||||
.expect("failed to initalize ffi platform");
|
.expect("failed to initalize ffi platform");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -14,10 +14,15 @@ crate-type = ["cdylib", "staticlib", "rlib"]
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt-tokio"]
|
default = ["rt-tokio"]
|
||||||
rt-async-std = ["async-std", "async_executors/async_std"]
|
rt-async-std = [
|
||||||
|
"async-std",
|
||||||
|
"async_executors/async_std",
|
||||||
|
"rtnetlink/smol_socket",
|
||||||
|
]
|
||||||
rt-tokio = [
|
rt-tokio = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
|
"rtnetlink/tokio_socket",
|
||||||
"async_executors/tokio_tp",
|
"async_executors/tokio_tp",
|
||||||
"async_executors/tokio_io",
|
"async_executors/tokio_io",
|
||||||
"async_executors/tokio_timer",
|
"async_executors/tokio_timer",
|
||||||
@ -25,7 +30,7 @@ rt-tokio = [
|
|||||||
rt-wasm-bindgen = ["async_executors/bindgen", "async_executors/timer"]
|
rt-wasm-bindgen = ["async_executors/bindgen", "async_executors/timer"]
|
||||||
|
|
||||||
veilid_tools_android_tests = ["dep:paranoid-android"]
|
veilid_tools_android_tests = ["dep:paranoid-android"]
|
||||||
veilid_tools_ios_tests = ["dep:oslog", "dep:tracing-oslog"]
|
veilid_tools_ios_tests = ["dep:tracing", "dep:oslog", "dep:tracing-oslog"]
|
||||||
tracing = ["dep:tracing", "dep:tracing-subscriber"]
|
tracing = ["dep:tracing", "dep:tracing-subscriber"]
|
||||||
network-result-extra = []
|
network-result-extra = []
|
||||||
network-result-info = []
|
network-result-info = []
|
||||||
@ -69,7 +74,7 @@ futures-util = { version = "0.3.28", default-features = false, features = [
|
|||||||
chrono = "0.4.31"
|
chrono = "0.4.31"
|
||||||
|
|
||||||
libc = "0.2.148"
|
libc = "0.2.148"
|
||||||
nix = { version = "0.27.1", features = [ "user" ] }
|
nix = { version = "0.27.1", features = ["user"] }
|
||||||
|
|
||||||
# Dependencies for WASM builds only
|
# Dependencies for WASM builds only
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
@ -82,6 +87,12 @@ getrandom = { version = "0.2", features = ["js"] }
|
|||||||
async-lock = "2.8.0"
|
async-lock = "2.8.0"
|
||||||
send_wrapper = { version = "0.6.0", features = ["futures"] }
|
send_wrapper = { version = "0.6.0", features = ["futures"] }
|
||||||
|
|
||||||
|
# Dependencies for Linux or Android
|
||||||
|
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies]
|
||||||
|
rtnetlink = { version = "=0.13.1", default-features = false }
|
||||||
|
netlink-sys = { version = "=0.8.5" }
|
||||||
|
netlink-packet-route = { version = "=0.17.1" }
|
||||||
|
|
||||||
# Dependencies for Android
|
# Dependencies for Android
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
jni = "0.21.1"
|
jni = "0.21.1"
|
||||||
@ -93,15 +104,18 @@ paranoid-android = { version = "0.2.1", optional = true }
|
|||||||
android_logger = "0.13.3"
|
android_logger = "0.13.3"
|
||||||
|
|
||||||
# Dependencies for Windows
|
# Dependencies for Windows
|
||||||
# [target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
# windows = { version = "^0", features = [ "Win32_NetworkManagement_Dns", "Win32_Foundation", "alloc" ]}
|
winapi = { version = "0.3.9", features = ["iptypes", "iphlpapi"] }
|
||||||
# windows-permissions = "^0"
|
|
||||||
|
|
||||||
# Dependencies for iOS
|
# Dependencies for iOS
|
||||||
[target.'cfg(target_os = "ios")'.dependencies]
|
[target.'cfg(target_os = "ios")'.dependencies]
|
||||||
oslog = { version = "0.2.0", optional = true }
|
oslog = { version = "0.2.0", optional = true }
|
||||||
tracing-oslog = { version = "0.1.2", optional = true }
|
tracing-oslog = { version = "0.1.2", optional = true }
|
||||||
|
|
||||||
|
# Dependenices for all Unix (Linux, Android, MacOS, iOS)
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
ifstructs = "0.1.1"
|
||||||
|
|
||||||
### DEV DEPENDENCIES
|
### DEV DEPENDENCIES
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -40,6 +40,7 @@ pub mod log_thru;
|
|||||||
pub mod must_join_handle;
|
pub mod must_join_handle;
|
||||||
pub mod must_join_single_future;
|
pub mod must_join_single_future;
|
||||||
pub mod mutable_future;
|
pub mod mutable_future;
|
||||||
|
pub mod network_interfaces;
|
||||||
pub mod network_result;
|
pub mod network_result;
|
||||||
pub mod random;
|
pub mod random;
|
||||||
pub mod single_shot_eventual;
|
pub mod single_shot_eventual;
|
||||||
@ -182,6 +183,8 @@ pub use must_join_single_future::*;
|
|||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use mutable_future::*;
|
pub use mutable_future::*;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
pub use network_interfaces::*;
|
||||||
|
#[doc(inline)]
|
||||||
pub use network_result::*;
|
pub use network_result::*;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use random::*;
|
pub use random::*;
|
||||||
|
@ -177,6 +177,14 @@ macro_rules! log_pstore {
|
|||||||
(warn $fmt:literal, $($arg:expr),+) => {
|
(warn $fmt:literal, $($arg:expr),+) => {
|
||||||
warn!(target:"pstore", $fmt, $($arg),+);
|
warn!(target:"pstore", $fmt, $($arg),+);
|
||||||
};
|
};
|
||||||
|
(debug $text:expr) => { debug!(
|
||||||
|
target: "pstore",
|
||||||
|
"{}",
|
||||||
|
$text,
|
||||||
|
)};
|
||||||
|
(debug $fmt:literal, $($arg:expr),+) => {
|
||||||
|
debug!(target:"pstore", $fmt, $($arg),+);
|
||||||
|
};
|
||||||
($text:expr) => {trace!(
|
($text:expr) => {trace!(
|
||||||
target: "pstore",
|
target: "pstore",
|
||||||
"{}",
|
"{}",
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
|
#![cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use libc::{
|
use libc::{
|
||||||
close, freeifaddrs, getifaddrs, if_nametoindex, ifaddrs, ioctl, pid_t, sockaddr, sockaddr_in6,
|
close, freeifaddrs, getifaddrs, if_nametoindex, ifaddrs, ioctl, pid_t, sockaddr, sockaddr_in6,
|
||||||
socket, sysctl, time_t, AF_INET6, CTL_NET, IFF_BROADCAST, IFF_LOOPBACK, IFF_RUNNING, IFNAMSIZ,
|
socket, sysctl, time_t, AF_INET6, CTL_NET, IFF_BROADCAST, IFF_LOOPBACK, IFF_POINTOPOINT,
|
||||||
NET_RT_FLAGS, PF_ROUTE, RTAX_DST, RTAX_GATEWAY, RTAX_MAX, RTA_DST, RTA_GATEWAY, RTF_GATEWAY,
|
IFF_RUNNING, IFNAMSIZ, NET_RT_FLAGS, PF_ROUTE, RTAX_DST, RTAX_GATEWAY, RTAX_MAX, RTA_DST,
|
||||||
SOCK_DGRAM,
|
RTA_GATEWAY, RTF_GATEWAY, SOCK_DGRAM,
|
||||||
};
|
};
|
||||||
use sockaddr_tools::SockAddr;
|
use sockaddr_tools::SockAddr;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
@ -13,12 +14,15 @@ use std::io;
|
|||||||
use std::os::raw::{c_int, c_uchar, c_ulong, c_ushort, c_void};
|
use std::os::raw::{c_int, c_uchar, c_ulong, c_ushort, c_void};
|
||||||
|
|
||||||
const SIOCGIFAFLAG_IN6: c_ulong = 0xC1206949;
|
const SIOCGIFAFLAG_IN6: c_ulong = 0xC1206949;
|
||||||
|
const SIOCGIFALIFETIME_IN6: c_ulong = 0xC1206951;
|
||||||
const IN6_IFF_TENTATIVE: c_ushort = 0x0002;
|
const IN6_IFF_TENTATIVE: c_ushort = 0x0002;
|
||||||
const IN6_IFF_DUPLICATED: c_ushort = 0x0004;
|
const IN6_IFF_DUPLICATED: c_ushort = 0x0004;
|
||||||
const IN6_IFF_DETACHED: c_ushort = 0x0008;
|
const IN6_IFF_DETACHED: c_ushort = 0x0008;
|
||||||
|
const IN6_IFF_AUTOCONF: c_ushort = 0x0040;
|
||||||
const IN6_IFF_TEMPORARY: c_ushort = 0x0080;
|
const IN6_IFF_TEMPORARY: c_ushort = 0x0080;
|
||||||
const IN6_IFF_DEPRECATED: c_ushort = 0x0010;
|
const IN6_IFF_DEPRECATED: c_ushort = 0x0010;
|
||||||
const IN6_IFF_DYNAMIC: c_ushort = 0x0100;
|
const IN6_IFF_DYNAMIC: c_ushort = 0x0100;
|
||||||
|
const IN6_IFF_SECURED: c_ushort = 0x0400;
|
||||||
|
|
||||||
macro_rules! set_name {
|
macro_rules! set_name {
|
||||||
($name_field:expr, $name_str:expr) => {{
|
($name_field:expr, $name_str:expr) => {{
|
||||||
@ -198,6 +202,9 @@ impl in6_ifreq {
|
|||||||
pub fn get_flags6(&self) -> c_ushort {
|
pub fn get_flags6(&self) -> c_ushort {
|
||||||
unsafe { self.ifr_ifru.ifru_flags6 as c_ushort }
|
unsafe { self.ifr_ifru.ifru_flags6 as c_ushort }
|
||||||
}
|
}
|
||||||
|
pub fn get_ia6t_expire(&self) -> time_t {
|
||||||
|
unsafe { self.ifr_ifru.ifru_lifetime.ia6t_expire as time_t }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_broadcast(ifaddr: &ifaddrs) -> Option<IpAddr> {
|
pub fn do_broadcast(ifaddr: &ifaddrs) -> Option<IpAddr> {
|
||||||
@ -267,13 +274,13 @@ pub struct PlatformSupportApple {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PlatformSupportApple {
|
impl PlatformSupportApple {
|
||||||
pub fn new() -> EyreResult<Self> {
|
pub fn new() -> Self {
|
||||||
Ok(PlatformSupportApple {
|
PlatformSupportApple {
|
||||||
default_route_interfaces: BTreeSet::new(),
|
default_route_interfaces: BTreeSet::new(),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn refresh_default_route_interfaces(&mut self) -> EyreResult<()> {
|
async fn refresh_default_route_interfaces(&mut self) {
|
||||||
self.default_route_interfaces.clear();
|
self.default_route_interfaces.clear();
|
||||||
|
|
||||||
let mut mib = [CTL_NET, PF_ROUTE, 0, 0, NET_RT_FLAGS, RTF_GATEWAY];
|
let mut mib = [CTL_NET, PF_ROUTE, 0, 0, NET_RT_FLAGS, RTF_GATEWAY];
|
||||||
@ -293,7 +300,8 @@ impl PlatformSupportApple {
|
|||||||
)
|
)
|
||||||
} < 0
|
} < 0
|
||||||
{
|
{
|
||||||
bail!("Unable to get memory size for routing table");
|
error!("Unable to get memory size for routing table");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a buffer
|
// Allocate a buffer
|
||||||
@ -311,7 +319,8 @@ impl PlatformSupportApple {
|
|||||||
)
|
)
|
||||||
} < 0
|
} < 0
|
||||||
{
|
{
|
||||||
bail!("Unable to get memory size for routing table");
|
error!("Unable to get memory size for routing table");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process each routing message
|
// Process each routing message
|
||||||
@ -360,61 +369,68 @@ impl PlatformSupportApple {
|
|||||||
|
|
||||||
mib_ptr = unsafe { mib_ptr.add((*rt).rtm_msglen.into()) };
|
mib_ptr = unsafe { mib_ptr.add((*rt).rtm_msglen.into()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_interface_flags(&self, index: u32, flags: c_int) -> EyreResult<InterfaceFlags> {
|
fn get_interface_flags(&self, index: u32, flags: c_int) -> InterfaceFlags {
|
||||||
Ok(InterfaceFlags {
|
InterfaceFlags {
|
||||||
is_loopback: (flags & IFF_LOOPBACK) != 0,
|
is_loopback: (flags & IFF_LOOPBACK) != 0,
|
||||||
is_running: (flags & IFF_RUNNING) != 0,
|
is_running: (flags & IFF_RUNNING) != 0,
|
||||||
|
is_point_to_point: (flags & IFF_POINTOPOINT) != 0,
|
||||||
has_default_route: self.default_route_interfaces.contains(&index),
|
has_default_route: self.default_route_interfaces.contains(&index),
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_address_flags(ifname: &str, addr: sockaddr_in6) -> io::Result<AddressFlags> {
|
||||||
|
let sock = unsafe { socket(AF_INET6, SOCK_DGRAM, 0) };
|
||||||
|
if sock < 0 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_address_flags(ifname: &str, addr: sockaddr_in6) -> EyreResult<AddressFlags> {
|
|
||||||
let mut req = in6_ifreq::from_name(ifname).unwrap();
|
let mut req = in6_ifreq::from_name(ifname).unwrap();
|
||||||
req.set_addr(addr);
|
req.set_addr(addr);
|
||||||
|
|
||||||
let sock = unsafe { socket(AF_INET6, SOCK_DGRAM, 0) };
|
|
||||||
if sock < 0 {
|
|
||||||
bail!("Socket error {:?}", io::Error::last_os_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = unsafe { ioctl(sock, SIOCGIFAFLAG_IN6, &mut req) };
|
let res = unsafe { ioctl(sock, SIOCGIFAFLAG_IN6, &mut req) };
|
||||||
unsafe { close(sock) };
|
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
bail!(
|
unsafe { close(sock) };
|
||||||
"SIOCGIFAFLAG_IN6 failed with error on device '{}': {:?}",
|
return Err(io::Error::last_os_error());
|
||||||
ifname,
|
|
||||||
io::Error::last_os_error()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let flags = req.get_flags6();
|
let flags = req.get_flags6();
|
||||||
|
|
||||||
Ok(AddressFlags {
|
let mut req = in6_ifreq::from_name(ifname).unwrap();
|
||||||
is_temporary: (flags & IN6_IFF_TEMPORARY) != 0,
|
req.set_addr(addr);
|
||||||
is_dynamic: (flags & IN6_IFF_DYNAMIC) != 0,
|
|
||||||
is_preferred: (flags
|
let res = unsafe { ioctl(sock, SIOCGIFALIFETIME_IN6, &mut req) };
|
||||||
|
unsafe { close(sock) };
|
||||||
|
if res < 0 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
let expire = req.get_ia6t_expire();
|
||||||
|
|
||||||
|
let is_auto_generated_random_address =
|
||||||
|
flags & (IN6_IFF_SECURED | IN6_IFF_AUTOCONF) == (IN6_IFF_SECURED | IN6_IFF_AUTOCONF);
|
||||||
|
|
||||||
|
let is_temporary =
|
||||||
|
(flags & IN6_IFF_TEMPORARY) != 0 || (expire != 0 && is_auto_generated_random_address);
|
||||||
|
let is_dynamic = (flags & (IN6_IFF_DYNAMIC | IN6_IFF_AUTOCONF)) != 0;
|
||||||
|
let is_preferred = (flags
|
||||||
& (IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED))
|
& (IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED))
|
||||||
== 0,
|
== 0;
|
||||||
|
|
||||||
|
Ok(AddressFlags {
|
||||||
|
is_temporary,
|
||||||
|
is_dynamic,
|
||||||
|
is_preferred,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_interfaces(
|
pub async fn get_interfaces(
|
||||||
&mut self,
|
&mut self,
|
||||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||||
) -> EyreResult<()> {
|
) -> io::Result<()> {
|
||||||
self.refresh_default_route_interfaces().await?;
|
self.refresh_default_route_interfaces().await;
|
||||||
|
|
||||||
// If we have no routes, this isn't going to work
|
|
||||||
if self.default_route_interfaces.is_empty() {
|
|
||||||
bail!("no routes available for NetworkInterfaces");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask for all the addresses we have
|
// Ask for all the addresses we have
|
||||||
let ifaddrs = IfAddrs::new().wrap_err("failed to get interface addresses")?;
|
let ifaddrs = IfAddrs::new()?;
|
||||||
for ifaddr in ifaddrs.iter() {
|
for ifaddr in ifaddrs.iter() {
|
||||||
// Get the interface name
|
// Get the interface name
|
||||||
let ifname = unsafe { CStr::from_ptr(ifaddr.ifa_name) }
|
let ifname = unsafe { CStr::from_ptr(ifaddr.ifa_name) }
|
||||||
@ -427,7 +443,7 @@ impl PlatformSupportApple {
|
|||||||
// Map the name to a NetworkInterface
|
// Map the name to a NetworkInterface
|
||||||
if !interfaces.contains_key(&ifname) {
|
if !interfaces.contains_key(&ifname) {
|
||||||
// If we have no NetworkInterface yet, make one
|
// If we have no NetworkInterface yet, make one
|
||||||
let flags = self.get_interface_flags(ifindex, ifaddr.ifa_flags as c_int)?;
|
let flags = self.get_interface_flags(ifindex, ifaddr.ifa_flags as c_int);
|
||||||
interfaces.insert(ifname.clone(), NetworkInterface::new(ifname.clone(), flags));
|
interfaces.insert(ifname.clone(), NetworkInterface::new(ifname.clone(), flags));
|
||||||
}
|
}
|
||||||
let intf = interfaces.get_mut(&ifname).unwrap();
|
let intf = interfaces.get_mut(&ifname).unwrap();
|
@ -1,18 +1,17 @@
|
|||||||
|
mod apple;
|
||||||
|
mod netlink;
|
||||||
|
mod sockaddr_tools;
|
||||||
mod tools;
|
mod tools;
|
||||||
|
mod windows;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(any(target_os = "linux", target_os = "android"))] {
|
if #[cfg(any(target_os = "linux", target_os = "android"))] {
|
||||||
mod netlink;
|
|
||||||
use self::netlink::PlatformSupportNetlink as PlatformSupport;
|
use self::netlink::PlatformSupportNetlink as PlatformSupport;
|
||||||
} else if #[cfg(target_os = "windows")] {
|
} else if #[cfg(target_os = "windows")] {
|
||||||
mod windows;
|
|
||||||
mod sockaddr_tools;
|
|
||||||
use self::windows::PlatformSupportWindows as PlatformSupport;
|
use self::windows::PlatformSupportWindows as PlatformSupport;
|
||||||
} else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
|
} else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
|
||||||
mod apple;
|
|
||||||
mod sockaddr_tools;
|
|
||||||
use self::apple::PlatformSupportApple as PlatformSupport;
|
use self::apple::PlatformSupportApple as PlatformSupport;
|
||||||
} else {
|
} else {
|
||||||
compile_error!("No network interfaces support for this platform!");
|
compile_error!("No network interfaces support for this platform!");
|
||||||
@ -74,6 +73,7 @@ pub struct Ifv6Addr {
|
|||||||
pub struct InterfaceFlags {
|
pub struct InterfaceFlags {
|
||||||
pub is_loopback: bool,
|
pub is_loopback: bool,
|
||||||
pub is_running: bool,
|
pub is_running: bool,
|
||||||
|
pub is_point_to_point: bool,
|
||||||
pub has_default_route: bool,
|
pub has_default_route: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,6 +261,10 @@ impl NetworkInterface {
|
|||||||
self.flags.is_loopback
|
self.flags.is_loopback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_point_to_point(&self) -> bool {
|
||||||
|
self.flags.is_point_to_point
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_running(&self) -> bool {
|
pub fn is_running(&self) -> bool {
|
||||||
self.flags.is_running
|
self.flags.is_running
|
||||||
}
|
}
|
||||||
@ -310,13 +314,22 @@ impl fmt::Debug for NetworkInterfaces {
|
|||||||
.finish()?;
|
.finish()?;
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
writeln!(f, "// best_addresses: {:?}", inner.interface_address_cache)?;
|
writeln!(
|
||||||
|
f,
|
||||||
|
"// stable_addresses: {:?}",
|
||||||
|
inner.interface_address_cache
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
impl Default for NetworkInterfaces {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl NetworkInterfaces {
|
impl NetworkInterfaces {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -339,14 +352,14 @@ impl NetworkInterfaces {
|
|||||||
inner.interface_address_cache.clear();
|
inner.interface_address_cache.clear();
|
||||||
inner.valid = false;
|
inner.valid = false;
|
||||||
}
|
}
|
||||||
// returns Ok(false) if refresh had no changes, Ok(true) if changes were present
|
// returns false if refresh had no changes, true if changes were present
|
||||||
pub async fn refresh(&self) -> EyreResult<bool> {
|
pub async fn refresh(&self) -> std::io::Result<bool> {
|
||||||
let mut last_interfaces = {
|
let mut last_interfaces = {
|
||||||
let mut last_interfaces = BTreeMap::<String, NetworkInterface>::new();
|
let mut last_interfaces = BTreeMap::<String, NetworkInterface>::new();
|
||||||
let mut platform_support = PlatformSupport::new()?;
|
let mut platform_support = PlatformSupport::new();
|
||||||
if let Err(e) = platform_support.get_interfaces(&mut last_interfaces).await {
|
platform_support
|
||||||
debug!("no network interfaces are enabled: {}", e);
|
.get_interfaces(&mut last_interfaces)
|
||||||
}
|
.await?;
|
||||||
last_interfaces
|
last_interfaces
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -356,16 +369,16 @@ impl NetworkInterfaces {
|
|||||||
|
|
||||||
if last_interfaces != inner.interfaces {
|
if last_interfaces != inner.interfaces {
|
||||||
// get last address cache
|
// get last address cache
|
||||||
let old_best_addresses = inner.interface_address_cache.clone();
|
let old_stable_addresses = inner.interface_address_cache.clone();
|
||||||
|
|
||||||
// redo the address cache
|
// redo the address cache
|
||||||
Self::cache_best_addresses(&mut inner);
|
Self::cache_stable_addresses(&mut inner);
|
||||||
|
|
||||||
// See if our best addresses have changed
|
// See if our best addresses have changed
|
||||||
if old_best_addresses != inner.interface_address_cache {
|
if old_stable_addresses != inner.interface_address_cache {
|
||||||
trace!(
|
debug!(
|
||||||
"Network interface addresses changed: {:?}",
|
"Network interface addresses changed: \nFrom: {:?}\n To: {:?}\n",
|
||||||
inner.interface_address_cache
|
old_stable_addresses, inner.interface_address_cache
|
||||||
);
|
);
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
@ -380,18 +393,22 @@ impl NetworkInterfaces {
|
|||||||
f(&inner.interfaces)
|
f(&inner.interfaces)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn best_addresses(&self) -> Vec<IpAddr> {
|
pub fn stable_addresses(&self) -> Vec<IpAddr> {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
inner.interface_address_cache.clone()
|
inner.interface_address_cache.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
fn cache_best_addresses(inner: &mut NetworkInterfacesInner) {
|
fn cache_stable_addresses(inner: &mut NetworkInterfacesInner) {
|
||||||
// Reduce interfaces to their best routable ip addresses
|
// Reduce interfaces to their best routable ip addresses
|
||||||
let mut intf_addrs = Vec::new();
|
let mut intf_addrs = Vec::new();
|
||||||
for intf in inner.interfaces.values() {
|
for intf in inner.interfaces.values() {
|
||||||
if !intf.is_running() || !intf.has_default_route() || intf.is_loopback() {
|
if !intf.is_running()
|
||||||
|
|| !intf.has_default_route()
|
||||||
|
|| intf.is_loopback()
|
||||||
|
|| intf.is_point_to_point()
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(pipv4) = intf.primary_ipv4() {
|
if let Some(pipv4) = intf.primary_ipv4() {
|
@ -1,17 +1,19 @@
|
|||||||
|
#![cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use alloc::collections::btree_map::Entry;
|
|
||||||
use futures_util::stream::TryStreamExt;
|
use futures_util::stream::TryStreamExt;
|
||||||
use ifstructs::ifreq;
|
use ifstructs::ifreq;
|
||||||
use libc::{
|
use libc::{
|
||||||
close, if_indextoname, ioctl, socket, IFF_LOOPBACK, IFF_RUNNING, IF_NAMESIZE, SIOCGIFFLAGS,
|
close, if_indextoname, ioctl, socket, IFF_LOOPBACK, IFF_POINTOPOINT, IFF_RUNNING, IF_NAMESIZE,
|
||||||
SOCK_DGRAM,
|
SIOCGIFFLAGS, SOCK_DGRAM,
|
||||||
};
|
};
|
||||||
use netlink_packet_route::{
|
use netlink_packet_route::{
|
||||||
nlas::address::Nla, AddressMessage, AF_INET, AF_INET6, IFA_F_DADFAILED, IFA_F_DEPRECATED,
|
nlas::address::Nla, AddressMessage, AF_INET, AF_INET6, IFA_F_DADFAILED, IFA_F_DEPRECATED,
|
||||||
IFA_F_OPTIMISTIC, IFA_F_PERMANENT, IFA_F_TEMPORARY, IFA_F_TENTATIVE,
|
IFA_F_OPTIMISTIC, IFA_F_PERMANENT, IFA_F_TEMPORARY, IFA_F_TENTATIVE,
|
||||||
};
|
};
|
||||||
use rtnetlink::{new_connection_with_socket, Handle, IpVersion};
|
use rtnetlink::{new_connection_with_socket, Handle, IpVersion};
|
||||||
|
use std::collections::btree_map::Entry;
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature="rt-async-std")] {
|
if #[cfg(feature="rt-async-std")] {
|
||||||
use netlink_sys::{SmolSocket as RTNetLinkSocket};
|
use netlink_sys::{SmolSocket as RTNetLinkSocket};
|
||||||
@ -27,16 +29,16 @@ use std::io;
|
|||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
use tools::*;
|
use tools::*;
|
||||||
|
|
||||||
fn get_interface_name(index: u32) -> EyreResult<String> {
|
fn get_interface_name(index: u32) -> io::Result<String> {
|
||||||
let mut ifnamebuf = [0u8; (IF_NAMESIZE + 1)];
|
let mut ifnamebuf = [0u8; (IF_NAMESIZE + 1)];
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(all(any(target_os = "android", target_os="linux"), any(target_arch = "arm", target_arch = "aarch64")))] {
|
if #[cfg(all(any(target_os = "android", target_os="linux"), any(target_arch = "arm", target_arch = "aarch64")))] {
|
||||||
if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr()) }.is_null() {
|
if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr()) }.is_null() {
|
||||||
bail!("if_indextoname returned null");
|
bail_io_error_other!("if_indextoname returned null");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr() as *mut i8) }.is_null() {
|
if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr() as *mut i8) }.is_null() {
|
||||||
bail!("if_indextoname returned null");
|
bail_io_error_other!("if_indextoname returned null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,11 +46,11 @@ fn get_interface_name(index: u32) -> EyreResult<String> {
|
|||||||
let ifnamebuflen = ifnamebuf
|
let ifnamebuflen = ifnamebuf
|
||||||
.iter()
|
.iter()
|
||||||
.position(|c| *c == 0u8)
|
.position(|c| *c == 0u8)
|
||||||
.ok_or_else(|| eyre!("null not found in interface name"))?;
|
.ok_or_else(|| io_error_other!("null not found in interface name"))?;
|
||||||
let ifname_str = CStr::from_bytes_with_nul(&ifnamebuf[0..=ifnamebuflen])
|
let ifname_str = CStr::from_bytes_with_nul(&ifnamebuf[0..=ifnamebuflen])
|
||||||
.wrap_err("failed to convert interface name")?
|
.map_err(|e| io_error_other!(e))?
|
||||||
.to_str()
|
.to_str()
|
||||||
.wrap_err("invalid characters in interface name")?;
|
.map_err(|e| io_error_other!(e))?;
|
||||||
Ok(ifname_str.to_owned())
|
Ok(ifname_str.to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,16 +71,16 @@ pub struct PlatformSupportNetlink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PlatformSupportNetlink {
|
impl PlatformSupportNetlink {
|
||||||
pub fn new() -> EyreResult<Self> {
|
pub fn new() -> Self {
|
||||||
Ok(PlatformSupportNetlink {
|
PlatformSupportNetlink {
|
||||||
connection_jh: None,
|
connection_jh: None,
|
||||||
handle: None,
|
handle: None,
|
||||||
default_route_interfaces: BTreeSet::new(),
|
default_route_interfaces: BTreeSet::new(),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out which interfaces have default routes
|
// Figure out which interfaces have default routes
|
||||||
async fn refresh_default_route_interfaces(&mut self) -> EyreResult<()> {
|
async fn refresh_default_route_interfaces(&mut self) {
|
||||||
self.default_route_interfaces.clear();
|
self.default_route_interfaces.clear();
|
||||||
let mut routesv4 = self
|
let mut routesv4 = self
|
||||||
.handle
|
.handle
|
||||||
@ -110,15 +112,14 @@ impl PlatformSupportNetlink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_interface_flags(&self, index: u32, ifname: &str) -> EyreResult<InterfaceFlags> {
|
fn get_interface_flags(&self, index: u32, ifname: &str) -> io::Result<InterfaceFlags> {
|
||||||
let mut req = ifreq::from_name(ifname).wrap_err("failed to convert interface name")?;
|
let mut req = ifreq::from_name(ifname)?;
|
||||||
|
|
||||||
let sock = unsafe { socket(AF_INET as i32, SOCK_DGRAM, 0) };
|
let sock = unsafe { socket(AF_INET as i32, SOCK_DGRAM, 0) };
|
||||||
if sock < 0 {
|
if sock < 0 {
|
||||||
return Err(io::Error::last_os_error()).wrap_err("failed to create socket");
|
return Err(io::Error::last_os_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
@ -130,7 +131,7 @@ impl PlatformSupportNetlink {
|
|||||||
}
|
}
|
||||||
unsafe { close(sock) };
|
unsafe { close(sock) };
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
return Err(io::Error::last_os_error()).wrap_err("failed to close socket");
|
return Err(io::Error::last_os_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
let flags = req.get_flags() as c_int;
|
let flags = req.get_flags() as c_int;
|
||||||
@ -138,6 +139,7 @@ impl PlatformSupportNetlink {
|
|||||||
Ok(InterfaceFlags {
|
Ok(InterfaceFlags {
|
||||||
is_loopback: (flags & IFF_LOOPBACK) != 0,
|
is_loopback: (flags & IFF_LOOPBACK) != 0,
|
||||||
is_running: (flags & IFF_RUNNING) != 0,
|
is_running: (flags & IFF_RUNNING) != 0,
|
||||||
|
is_point_to_point: (flags & IFF_POINTOPOINT) != 0,
|
||||||
has_default_route: self.default_route_interfaces.contains(&index),
|
has_default_route: self.default_route_interfaces.contains(&index),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -244,23 +246,14 @@ impl PlatformSupportNetlink {
|
|||||||
async fn get_interfaces_internal(
|
async fn get_interfaces_internal(
|
||||||
&mut self,
|
&mut self,
|
||||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||||
) -> EyreResult<()> {
|
) -> io::Result<()> {
|
||||||
// Refresh the routes
|
// Refresh the routes
|
||||||
self.refresh_default_route_interfaces().await?;
|
self.refresh_default_route_interfaces().await;
|
||||||
|
|
||||||
// If we have no routes, this isn't going to work
|
|
||||||
if self.default_route_interfaces.is_empty() {
|
|
||||||
bail!("no routes available for NetworkInterfaces");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask for all the addresses we have
|
// Ask for all the addresses we have
|
||||||
let mut names = BTreeMap::<u32, String>::new();
|
let mut names = BTreeMap::<u32, String>::new();
|
||||||
let mut addresses = self.handle.as_ref().unwrap().address().get().execute();
|
let mut addresses = self.handle.as_ref().unwrap().address().get().execute();
|
||||||
while let Some(msg) = addresses
|
while let Some(msg) = addresses.try_next().await.map_err(|e| io_error_other!(e))? {
|
||||||
.try_next()
|
|
||||||
.await
|
|
||||||
.wrap_err("failed to iterate interface addresses")?
|
|
||||||
{
|
|
||||||
// Have we seen this interface index yet?
|
// Have we seen this interface index yet?
|
||||||
// Get the name from the index, cached, if we can
|
// Get the name from the index, cached, if we can
|
||||||
let ifname = match names.entry(msg.header.index) {
|
let ifname = match names.entry(msg.header.index) {
|
||||||
@ -318,10 +311,9 @@ impl PlatformSupportNetlink {
|
|||||||
pub async fn get_interfaces(
|
pub async fn get_interfaces(
|
||||||
&mut self,
|
&mut self,
|
||||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||||
) -> EyreResult<()> {
|
) -> io::Result<()> {
|
||||||
// Get the netlink connection
|
// Get the netlink connection
|
||||||
let (connection, handle, _) = new_connection_with_socket::<RTNetLinkSocket>()
|
let (connection, handle, _) = new_connection_with_socket::<RTNetLinkSocket>()?;
|
||||||
.wrap_err("failed to create rtnetlink socket")?;
|
|
||||||
|
|
||||||
// Spawn a connection handler
|
// Spawn a connection handler
|
||||||
let connection_jh = spawn(connection);
|
let connection_jh = spawn(connection);
|
@ -1,3 +1,4 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
// Copyright 2018 MaidSafe.net limited.
|
// Copyright 2018 MaidSafe.net limited.
|
||||||
//
|
//
|
||||||
// This SAFE Network Software is licensed to you under the MIT license <LICENSE-MIT
|
// This SAFE Network Software is licensed to you under the MIT license <LICENSE-MIT
|
||||||
@ -48,13 +49,7 @@ impl SockAddr {
|
|||||||
((sa.sin_addr.s_addr >> 16) & 255) as u8,
|
((sa.sin_addr.s_addr >> 16) & 255) as u8,
|
||||||
((sa.sin_addr.s_addr >> 24) & 255) as u8,
|
((sa.sin_addr.s_addr >> 24) & 255) as u8,
|
||||||
))),
|
))),
|
||||||
Some(SockAddrIn::In6(sa)) => {
|
Some(SockAddrIn::In6(sa)) => Some(IpAddr::V6(Ipv6Addr::from(sa.sin6_addr.s6_addr))),
|
||||||
// Ignore all fe80:: addresses as these are link locals
|
|
||||||
if sa.sin6_addr.s6_addr[0] == 0xfe && sa.sin6_addr.s6_addr[1] == 0x80 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(IpAddr::V6(Ipv6Addr::from(sa.sin6_addr.s6_addr)))
|
|
||||||
}
|
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,10 +59,6 @@ impl SockAddr {
|
|||||||
match self.sockaddr_in() {
|
match self.sockaddr_in() {
|
||||||
Some(SockAddrIn::In(sa)) => {
|
Some(SockAddrIn::In(sa)) => {
|
||||||
let s_addr = unsafe { sa.sin_addr.S_un.S_addr() };
|
let s_addr = unsafe { sa.sin_addr.S_un.S_addr() };
|
||||||
// Ignore all 169.254.x.x addresses as these are not active interfaces
|
|
||||||
if s_addr & 65535 == 0xfea9 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(IpAddr::V4(Ipv4Addr::new(
|
Some(IpAddr::V4(Ipv4Addr::new(
|
||||||
(s_addr & 255u32) as u8,
|
(s_addr & 255u32) as u8,
|
||||||
((s_addr >> 8) & 255u32) as u8,
|
((s_addr >> 8) & 255u32) as u8,
|
||||||
@ -77,10 +68,6 @@ impl SockAddr {
|
|||||||
}
|
}
|
||||||
Some(SockAddrIn::In6(sa)) => {
|
Some(SockAddrIn::In6(sa)) => {
|
||||||
let s6_addr = unsafe { sa.sin6_addr.u.Byte() };
|
let s6_addr = unsafe { sa.sin6_addr.u.Byte() };
|
||||||
// Ignore all fe80:: addresses as these are link locals
|
|
||||||
if s6_addr[0] == 0xfe && s6_addr[1] == 0x80 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(IpAddr::V6(Ipv6Addr::from(*s6_addr)))
|
Some(IpAddr::V6(Ipv6Addr::from(*s6_addr)))
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
@ -1,3 +1,5 @@
|
|||||||
|
#![cfg(target_os = "windows")]
|
||||||
|
|
||||||
// Copyright 2018 MaidSafe.net limited.
|
// Copyright 2018 MaidSafe.net limited.
|
||||||
//
|
//
|
||||||
// This SAFE Network Software is licensed to you under the MIT license <LICENSE-MIT
|
// This SAFE Network Software is licensed to you under the MIT license <LICENSE-MIT
|
||||||
@ -13,7 +15,7 @@ use libc::{self, c_ulong, c_void, size_t};
|
|||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::{io, ptr};
|
use std::{io, ptr};
|
||||||
use winapi::shared::ifdef::IfOperStatusUp;
|
use winapi::shared::ifdef::IfOperStatusUp;
|
||||||
use winapi::shared::ipifcons::IF_TYPE_SOFTWARE_LOOPBACK;
|
use winapi::shared::ipifcons::{IF_TYPE_SOFTWARE_LOOPBACK, IF_TYPE_TUNNEL};
|
||||||
use winapi::shared::nldef::{
|
use winapi::shared::nldef::{
|
||||||
IpDadStatePreferred, IpPrefixOriginDhcp, IpSuffixOriginDhcp, IpSuffixOriginRandom,
|
IpDadStatePreferred, IpPrefixOriginDhcp, IpSuffixOriginDhcp, IpSuffixOriginRandom,
|
||||||
};
|
};
|
||||||
@ -28,14 +30,15 @@ use winapi::um::iptypes::{
|
|||||||
pub struct PlatformSupportWindows {}
|
pub struct PlatformSupportWindows {}
|
||||||
|
|
||||||
impl PlatformSupportWindows {
|
impl PlatformSupportWindows {
|
||||||
pub fn new() -> EyreResult<Self> {
|
pub fn new() -> Self {
|
||||||
Ok(PlatformSupportWindows {})
|
PlatformSupportWindows {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_interface_flags(intf: &IpAdapterAddresses) -> InterfaceFlags {
|
fn get_interface_flags(intf: &IpAdapterAddresses) -> InterfaceFlags {
|
||||||
InterfaceFlags {
|
InterfaceFlags {
|
||||||
is_loopback: intf.get_flag_loopback(),
|
is_loopback: intf.get_flag_loopback(),
|
||||||
is_running: intf.get_flag_running(),
|
is_running: intf.get_flag_running(),
|
||||||
|
is_point_to_point: intf.get_flag_point_to_point(),
|
||||||
has_default_route: intf.get_has_default_route(),
|
has_default_route: intf.get_has_default_route(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,17 +57,9 @@ impl PlatformSupportWindows {
|
|||||||
pub async fn get_interfaces(
|
pub async fn get_interfaces(
|
||||||
&mut self,
|
&mut self,
|
||||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||||
) -> EyreResult<()> {
|
) -> io::Result<()> {
|
||||||
//self.refresh_default_route_interfaces().await?;
|
|
||||||
|
|
||||||
// If we have no routes, this isn't going to work
|
|
||||||
// if self.default_route_interfaces.is_empty() {
|
|
||||||
// return Err("no routes available for NetworkInterfaces".to_owned());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Iterate all the interfaces
|
// Iterate all the interfaces
|
||||||
let windows_interfaces =
|
let windows_interfaces = WindowsInterfaces::new()?;
|
||||||
WindowsInterfaces::new().wrap_err("failed to get windows interfaces")?;
|
|
||||||
for windows_interface in windows_interfaces.iter() {
|
for windows_interface in windows_interfaces.iter() {
|
||||||
// Get name
|
// Get name
|
||||||
let intf_name = windows_interface.name();
|
let intf_name = windows_interface.name();
|
||||||
@ -224,6 +219,9 @@ impl IpAdapterAddresses {
|
|||||||
pub fn get_flag_running(&self) -> bool {
|
pub fn get_flag_running(&self) -> bool {
|
||||||
unsafe { (*self.data).OperStatus == IfOperStatusUp }
|
unsafe { (*self.data).OperStatus == IfOperStatusUp }
|
||||||
}
|
}
|
||||||
|
pub fn get_flag_point_to_point(&self) -> bool {
|
||||||
|
unsafe { (*self.data).IfType == IF_TYPE_TUNNEL }
|
||||||
|
}
|
||||||
pub fn get_has_default_route(&self) -> bool {
|
pub fn get_has_default_route(&self) -> bool {
|
||||||
unsafe { !(*self.data).FirstGatewayAddress.is_null() }
|
unsafe { !(*self.data).FirstGatewayAddress.is_null() }
|
||||||
}
|
}
|
@ -15,20 +15,23 @@ pub extern "C" fn run_veilid_tools_tests() {
|
|||||||
pub fn veilid_tools_setup_ios_tests() {
|
pub fn veilid_tools_setup_ios_tests() {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "tracing")] {
|
if #[cfg(feature = "tracing")] {
|
||||||
|
use tracing::level_filters::LevelFilter;
|
||||||
use tracing_oslog::OsLogger;
|
use tracing_oslog::OsLogger;
|
||||||
use tracing_subscriber::prelude::*;
|
use tracing_subscriber::prelude::*;
|
||||||
|
use tracing_subscriber::filter::Targets;
|
||||||
|
|
||||||
let mut filters = filter::Targets::new();
|
let mut filters = Targets::new();
|
||||||
for ig in DEFAULT_LOG_IGNORE_LIST {
|
for ig in DEFAULT_LOG_IGNORE_LIST {
|
||||||
filters = filters.with_target(ig, filter::LevelFilter::OFF);
|
filters = filters.with_target(ig, LevelFilter::OFF);
|
||||||
}
|
}
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
|
.with(OsLogger::new("com.veilid.veilidtools-tests", "default"))
|
||||||
|
.with(LevelFilter::TRACE)
|
||||||
.with(filters)
|
.with(filters)
|
||||||
.with(filter::LevelFilter::TRACE)
|
|
||||||
.with(OsLogger::new("com.veilid.veilidtools-tests", ""))
|
|
||||||
.init();
|
.init();
|
||||||
} else {
|
} else {
|
||||||
use oslog::OsLogger;
|
use oslog::OsLogger;
|
||||||
|
use log::LevelFilter;
|
||||||
|
|
||||||
OsLogger::new("com.veilid.veilidtools-tests")
|
OsLogger::new("com.veilid.veilidtools-tests")
|
||||||
.level_filter(LevelFilter::Trace)
|
.level_filter(LevelFilter::Trace)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
mod test_assembly_buffer;
|
mod test_assembly_buffer;
|
||||||
mod test_async_peek_stream;
|
mod test_async_peek_stream;
|
||||||
|
mod test_network_interfaces;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -13,6 +14,8 @@ use super::*;
|
|||||||
pub async fn run_all_tests() {
|
pub async fn run_all_tests() {
|
||||||
info!("TEST: exec_test_host_interface");
|
info!("TEST: exec_test_host_interface");
|
||||||
test_host_interface::test_all().await;
|
test_host_interface::test_all().await;
|
||||||
|
info!("TEST: exec_test_network_interfaces");
|
||||||
|
test_network_interfaces::test_all().await;
|
||||||
info!("TEST: exec_test_async_peek_stream");
|
info!("TEST: exec_test_async_peek_stream");
|
||||||
test_async_peek_stream::test_all().await;
|
test_async_peek_stream::test_all().await;
|
||||||
info!("TEST: exec_test_async_tag_lock");
|
info!("TEST: exec_test_async_tag_lock");
|
||||||
@ -82,6 +85,15 @@ cfg_if! {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn run_test_network_interfaces() {
|
||||||
|
setup();
|
||||||
|
block_on(async {
|
||||||
|
test_network_interfaces::test_all().await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn run_test_async_peek_stream() {
|
fn run_test_async_peek_stream() {
|
||||||
|
@ -2,7 +2,7 @@ use crate::*;
|
|||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(not(target_arch = "wasm32"))] {
|
if #[cfg(not(target_arch = "wasm32"))] {
|
||||||
use intf::network_interfaces::NetworkInterfaces;
|
use network_interfaces::NetworkInterfaces;
|
||||||
|
|
||||||
pub async fn test_network_interfaces() {
|
pub async fn test_network_interfaces() {
|
||||||
info!("testing network interfaces");
|
info!("testing network interfaces");
|
Loading…
Reference in New Issue
Block a user