mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-10-01 01:26:08 -04:00
network interfaces work
This commit is contained in:
parent
cf2acc4bd5
commit
7ba6748cd2
123
Cargo.lock
generated
123
Cargo.lock
generated
@ -1668,6 +1668,16 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ifstructs"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b24d770f92a5ea876a33851b16553f21985bb83e7fe8e7e1f596ad75545e9581"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-codec"
|
||||
version = "0.5.1"
|
||||
@ -2102,6 +2112,71 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
|
||||
|
||||
[[package]]
|
||||
name = "netlink-packet-core"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8349128e95f5dabcb8a18587ad06b3ca7993e90c0c360b4a2abac0313ebce727"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"libc",
|
||||
"netlink-packet-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "netlink-packet-route"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fb5d54077de7c0904111e1d19b661b8cfccbc23d9ce5b6dbcc7362721e6e552"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"libc",
|
||||
"netlink-packet-core",
|
||||
"netlink-packet-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "netlink-packet-utils"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a008a56eceb0cab06739c7f37f15bda27f1147a14d0e7136e8c913b94f1441d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"paste",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "netlink-proto"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "073885f70c1d54fdc6148075e8e38a5e8a28179f59de5bd0fc6277cae4fec95a"
|
||||
dependencies = [
|
||||
"bytes 1.1.0",
|
||||
"futures",
|
||||
"log",
|
||||
"netlink-packet-core",
|
||||
"netlink-sys",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "netlink-sys"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed51a4602bb956eefef0ebc15f478bf9732fa3cc706e0a37112e654f41c5b92c"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"bytes 1.1.0",
|
||||
"futures",
|
||||
"libc",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.17.0"
|
||||
@ -2115,6 +2190,19 @@ dependencies = [
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1e25ee6b412c2a1e3fcb6a4499a5c1bfe7f43e014bdce9a6b6666e5aa2d187"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.23.0"
|
||||
@ -2421,6 +2509,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
@ -2831,6 +2925,21 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtnetlink"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa584f57f271d3fbd9f59503b090a0410a531c8cc272143669bf136c62ef409d"
|
||||
dependencies = [
|
||||
"async-global-executor",
|
||||
"futures",
|
||||
"log",
|
||||
"netlink-packet-route",
|
||||
"netlink-proto",
|
||||
"nix 0.22.0",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusqlite"
|
||||
version = "0.26.1"
|
||||
@ -3432,6 +3541,17 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838"
|
||||
dependencies = [
|
||||
"bytes 1.1.0",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
@ -3656,6 +3776,7 @@ dependencies = [
|
||||
"hashbrown",
|
||||
"hex",
|
||||
"if-addrs",
|
||||
"ifstructs",
|
||||
"jni",
|
||||
"jni-sys",
|
||||
"js-sys",
|
||||
@ -3663,6 +3784,7 @@ dependencies = [
|
||||
"keyvaluedb-sqlite",
|
||||
"keyvaluedb-web",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"lru",
|
||||
"maplit",
|
||||
@ -3673,6 +3795,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"parking_lot 0.11.2",
|
||||
"rand 0.7.3",
|
||||
"rtnetlink",
|
||||
"rusqlite",
|
||||
"rust-fsm",
|
||||
"rustls",
|
||||
|
@ -67,6 +67,7 @@ async_executors = { version = "^0", features = [ "async_std" ]}
|
||||
socket2 = "^0"
|
||||
bugsalot = "^0"
|
||||
chrono = "^0"
|
||||
libc = "^0"
|
||||
|
||||
# Dependencies for WASM builds only
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
@ -102,7 +103,7 @@ features = [
|
||||
'Window',
|
||||
]
|
||||
|
||||
# Dependencies specifically for Android
|
||||
# Dependencies for Android
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
jni = "^0"
|
||||
jni-sys = "^0"
|
||||
@ -111,6 +112,15 @@ ndk-glue = { version = "^0", features = ["logger"] }
|
||||
android_logger = { version = "^0" }
|
||||
backtrace = { version = "^0" }
|
||||
|
||||
# Dependenices for all Unix (Linux, Android, MacOS, iOS)
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
ifstructs = "^0"
|
||||
|
||||
# Dependencies for Linux or Android
|
||||
[target.'cfg(any(target_os = "android",target_os = "linux"))'.dependencies]
|
||||
rtnetlink = { version = "^0", default-features = false, features = [ "smol_socket" ] }
|
||||
|
||||
# Dependencies for iOS
|
||||
[target.'cfg(target_os = "ios")'.dependencies]
|
||||
simplelog = { version = "^0", optional = true }
|
||||
backtrace = { version = "^0", optional = true }
|
||||
|
@ -1061,7 +1061,9 @@ impl Network {
|
||||
info!("starting network");
|
||||
|
||||
// initialize interfaces
|
||||
self.inner.lock().interfaces.refresh()?;
|
||||
let mut interfaces = NetworkInterfaces::new();
|
||||
interfaces.refresh().await?;
|
||||
self.inner.lock().interfaces = interfaces;
|
||||
|
||||
// get protocol config
|
||||
let protocol_config = {
|
||||
|
@ -95,8 +95,11 @@ impl TableStore {
|
||||
let dbpath = Self::get_dbpath(&inner, &table_name)?;
|
||||
let cfg = DatabaseConfig::with_columns(column_count);
|
||||
let db =
|
||||
Database::open(dbpath, cfg).map_err(|e| format!("failed to open tabledb: {}", e))?;
|
||||
|
||||
Database::open(&dbpath, cfg).map_err(|e| format!("failed to open tabledb: {}", e))?;
|
||||
info!(
|
||||
"opened table store '{}' at path '{:?}' with {} columns",
|
||||
name, dbpath, column_count
|
||||
);
|
||||
let table_db = TableDB::new(table_name.clone(), self.clone(), db);
|
||||
|
||||
inner.opened.insert(table_name, table_db.weak_inner());
|
||||
|
@ -1,6 +1,8 @@
|
||||
mod android_get_if_addrs;
|
||||
// xxx : support for android older than API 24, if we need it someday
|
||||
//mod android_get_if_addrs;
|
||||
//pub use android_get_if_addrs::*;
|
||||
|
||||
mod get_directories;
|
||||
pub use android_get_if_addrs::*;
|
||||
pub use get_directories::*;
|
||||
|
||||
use crate::xx::*;
|
||||
|
@ -1,108 +0,0 @@
|
||||
#[cfg(target_os = "android")]
|
||||
pub use super::android::*;
|
||||
use crate::xx::*;
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub use if_addrs::*;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct NetworkInterface {
|
||||
name: String,
|
||||
is_loopback: bool,
|
||||
addrs: Vec<IfAddr>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl NetworkInterface {
|
||||
pub fn new(name: String, is_loopback: bool) -> Self {
|
||||
Self {
|
||||
name,
|
||||
is_loopback,
|
||||
addrs: Vec::new(),
|
||||
}
|
||||
}
|
||||
pub fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
pub fn is_loopback(&self) -> bool {
|
||||
self.is_loopback
|
||||
}
|
||||
pub fn primary_ipv4(&self) -> Option<Ipv4Addr> {
|
||||
for x in self.addrs.iter() {
|
||||
if let IfAddr::V4(a) = x {
|
||||
return Some(a.ip);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
pub fn primary_ipv6(&self) -> Option<Ipv6Addr> {
|
||||
for x in self.addrs.iter() {
|
||||
if let IfAddr::V6(a) = x {
|
||||
return Some(a.ip);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NetworkInterfaces {
|
||||
valid: bool,
|
||||
interfaces: BTreeMap<String, NetworkInterface>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl NetworkInterfaces {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
valid: false,
|
||||
interfaces: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.valid
|
||||
}
|
||||
pub fn clear(&mut self) {
|
||||
self.interfaces.clear();
|
||||
self.valid = false;
|
||||
}
|
||||
// returns Ok(false) if refresh had no changes, Ok(true) if changes were present
|
||||
pub fn refresh(&mut self) -> Result<bool, String> {
|
||||
self.valid = false;
|
||||
|
||||
let last_interfaces = core::mem::take(&mut self.interfaces);
|
||||
|
||||
let mut intfs = match get_if_addrs() {
|
||||
Err(e) => {
|
||||
return Err(format!("failed to refresh network interfaces: {}", e));
|
||||
}
|
||||
Ok(v) => v,
|
||||
};
|
||||
intfs.sort();
|
||||
|
||||
// debug!("{} interfaces found", intfs.len());
|
||||
for intf in intfs {
|
||||
// trace!("interface {} at {}", &intf.name, &intf.addr.ip());
|
||||
let ni = match self.interfaces.get_mut(&intf.name) {
|
||||
None => {
|
||||
self.interfaces.insert(
|
||||
intf.name.clone(),
|
||||
NetworkInterface::new(intf.name.clone(), intf.is_loopback()),
|
||||
);
|
||||
self.interfaces.get_mut(&intf.name).unwrap()
|
||||
}
|
||||
Some(v) => v,
|
||||
};
|
||||
|
||||
ni.addrs.push(intf.addr.clone());
|
||||
}
|
||||
|
||||
self.valid = true;
|
||||
|
||||
Ok(last_interfaces != self.interfaces)
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.interfaces.len()
|
||||
}
|
||||
pub fn iter(&self) -> std::collections::btree_map::Iter<String, NetworkInterface> {
|
||||
self.interfaces.iter()
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
use super::*;
|
||||
|
||||
pub struct PlatformSupportApple {
|
||||
//
|
||||
}
|
||||
|
||||
impl PlatformSupportApple {
|
||||
pub fn new() -> Result<Self, String> {
|
||||
Ok(PlatformSupportApple {})
|
||||
}
|
||||
|
||||
pub async fn get_interfaces(
|
||||
&mut self,
|
||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||
) -> Result<(), String> {
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -1,54 +1,8 @@
|
||||
use super::*;
|
||||
use crate::xx::*;
|
||||
pub use if_addrs::{IfAddr, Ifv4Addr, Ifv6Addr, Interface};
|
||||
use jni::objects::JValue;
|
||||
use std::io;
|
||||
|
||||
fn get_netmask_from_prefix_length_v4(out: &mut [u8; 4], mut plen: i16) {
|
||||
for n in 0..4 {
|
||||
out[n] = if plen >= 8 {
|
||||
plen -= 8;
|
||||
255u8
|
||||
} else if plen <= 0 {
|
||||
0u8
|
||||
} else {
|
||||
let v = 255u8 << (8 - plen);
|
||||
plen = 0;
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
fn get_netmask_from_prefix_length_v6(out: &mut [u8; 16], mut plen: i16) {
|
||||
for n in 0..16 {
|
||||
out[n] = if plen >= 8 {
|
||||
plen -= 8;
|
||||
255u8
|
||||
} else if plen == 0 {
|
||||
0u8
|
||||
} else {
|
||||
let v = 255u8 << (8 - plen);
|
||||
plen = 0;
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_unsigned_4(x: [i8; 4]) -> [u8; 4] {
|
||||
let mut out: [u8; 4] = [0u8; 4];
|
||||
for i in 0..4 {
|
||||
out[i] = x[i] as u8;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn convert_to_unsigned_16(x: [i8; 16]) -> [u8; 16] {
|
||||
let mut out: [u8; 16] = [0u8; 16];
|
||||
for i in 0..16 {
|
||||
out[i] = x[i] as u8;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
macro_rules! call_method_checked {
|
||||
($env:expr, $obj:expr, $name:expr, $sig:expr, $args:expr, $kind:ident) => {
|
||||
$env.call_method($obj, $name, $sig, $args)
|
@ -0,0 +1,232 @@
|
||||
#![allow(dead_code)]
|
||||
use super::*;
|
||||
use crate::xx::*;
|
||||
use hex::FromHex;
|
||||
use if_addrs::{IfAddr, Ifv4Addr, Ifv6Addr};
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Error, ErrorKind};
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ProcNetIpv6RouteEntry {
|
||||
dest_network: Ipv6Addr,
|
||||
dest_prefix: u8,
|
||||
src_network: Ipv6Addr,
|
||||
src_prefix: u8,
|
||||
next_hop: Ipv6Addr,
|
||||
metric: u32,
|
||||
ref_count: u32,
|
||||
use_count: u32,
|
||||
flags: u32,
|
||||
intf_name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ProcNetRouteEntry {
|
||||
iface: String,
|
||||
destination: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
flags: u16,
|
||||
ref_count: u32,
|
||||
use_count: u32,
|
||||
metric: u32,
|
||||
mask: Ipv4Addr,
|
||||
mtu: u32,
|
||||
window: u32,
|
||||
irtt: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlatformSupport {
|
||||
proc_net_ipv6_route: Vec<ProcNetIpv6RouteEntry>,
|
||||
proc_net_route: Vec<ProcNetRouteEntry>,
|
||||
}
|
||||
|
||||
impl PlatformSupport {
|
||||
fn parse_proc_net_ipv6_route() -> Result<Vec<ProcNetIpv6RouteEntry>, Error> {
|
||||
let file = File::open("/proc/net/ipv6_route")?;
|
||||
let reader = BufReader::new(file);
|
||||
let mut ipv6_route: Vec<ProcNetIpv6RouteEntry> = Vec::new();
|
||||
for line in reader.lines() {
|
||||
let line = line?;
|
||||
let line: Vec<&str> = line.split_ascii_whitespace().collect();
|
||||
if line.len() != 10 {
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
"Unexpected number of columns in /proc/net/ipv6_route",
|
||||
));
|
||||
}
|
||||
|
||||
let entry =
|
||||
ProcNetIpv6RouteEntry {
|
||||
dest_network: Ipv6Addr::from(<[u8; 16]>::from_hex(line[0]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse dest_network")
|
||||
})?),
|
||||
dest_prefix: <[u8; 1]>::from_hex(line[1]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse dest_prefix")
|
||||
})?[0],
|
||||
src_network: Ipv6Addr::from(<[u8; 16]>::from_hex(line[2]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse src_network")
|
||||
})?),
|
||||
src_prefix: <[u8; 1]>::from_hex(line[3]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse src_prefix")
|
||||
})?[0],
|
||||
next_hop: Ipv6Addr::from(<[u8; 16]>::from_hex(line[4]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse next_hop")
|
||||
})?),
|
||||
metric: u32::from_be_bytes(<[u8; 4]>::from_hex(line[5]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse metric")
|
||||
})?),
|
||||
ref_count: u32::from_be_bytes(<[u8; 4]>::from_hex(line[6]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse ref_count")
|
||||
})?),
|
||||
use_count: u32::from_be_bytes(<[u8; 4]>::from_hex(line[7]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse use_count")
|
||||
})?),
|
||||
flags: u32::from_be_bytes(<[u8; 4]>::from_hex(line[8]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse flags")
|
||||
})?),
|
||||
intf_name: String::from(line[9]),
|
||||
};
|
||||
|
||||
ipv6_route.push(entry)
|
||||
}
|
||||
|
||||
Ok(ipv6_route)
|
||||
}
|
||||
|
||||
fn parse_proc_net_route() -> Result<Vec<ProcNetRouteEntry>, Error> {
|
||||
let file = File::open("/proc/net/route")?;
|
||||
let reader = BufReader::new(file);
|
||||
let mut route: Vec<ProcNetRouteEntry> = Vec::new();
|
||||
let mut first = false;
|
||||
for line in reader.lines() {
|
||||
let line = line?;
|
||||
let line: Vec<&str> = line.split_ascii_whitespace().collect();
|
||||
if line.len() != 11 {
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
"Unexpected number of columns in /proc/net/route",
|
||||
));
|
||||
}
|
||||
if first {
|
||||
if line
|
||||
!= [
|
||||
"Iface",
|
||||
"Destination",
|
||||
"Gateway",
|
||||
"Flags",
|
||||
"RefCnt",
|
||||
"Use",
|
||||
"Metric",
|
||||
"Mask",
|
||||
"MTU",
|
||||
"Window",
|
||||
"IRTT",
|
||||
]
|
||||
{
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
format!("Unexpected columns in /proc/net/route: {:?}", line),
|
||||
));
|
||||
}
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
let entry =
|
||||
ProcNetRouteEntry {
|
||||
iface: String::from(line[0]),
|
||||
|
||||
destination: Ipv4Addr::from(u32::from_le_bytes(
|
||||
<[u8; 4]>::from_hex(line[0]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse destination")
|
||||
})?,
|
||||
)),
|
||||
gateway: Ipv4Addr::from(u32::from_le_bytes(
|
||||
<[u8; 4]>::from_hex(line[0]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse gateway")
|
||||
})?,
|
||||
)),
|
||||
flags: u16::from_be_bytes(<[u8; 2]>::from_hex(line[8]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse flags")
|
||||
})?),
|
||||
ref_count: u32::from_be_bytes(<[u8; 4]>::from_hex(line[6]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse ref_count")
|
||||
})?),
|
||||
use_count: u32::from_be_bytes(<[u8; 4]>::from_hex(line[7]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse use_count")
|
||||
})?),
|
||||
metric: u32::from_be_bytes(<[u8; 4]>::from_hex(line[5]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse metric")
|
||||
})?),
|
||||
mask: Ipv4Addr::from(u32::from_le_bytes(
|
||||
<[u8; 4]>::from_hex(line[0]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse mask")
|
||||
})?,
|
||||
)),
|
||||
mtu: u32::from_be_bytes(
|
||||
<[u8; 4]>::from_hex(line[5]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse mtu")
|
||||
})?,
|
||||
),
|
||||
window: u32::from_be_bytes(<[u8; 4]>::from_hex(line[5]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse window")
|
||||
})?),
|
||||
irtt: u32::from_be_bytes(
|
||||
<[u8; 4]>::from_hex(line[5]).map_err(|_| {
|
||||
Error::new(ErrorKind::InvalidData, "Unable to parse irtt")
|
||||
})?,
|
||||
),
|
||||
};
|
||||
|
||||
route.push(entry)
|
||||
}
|
||||
|
||||
Ok(route)
|
||||
}
|
||||
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
// Read /proc/net/ipv6_route
|
||||
let proc_net_ipv6_route = Self::parse_proc_net_ipv6_route().unwrap_or_default();
|
||||
// Read /proc/net/route
|
||||
let proc_net_route = Self::parse_proc_net_route().unwrap_or_default();
|
||||
|
||||
trace!("proc_net_ipv6_route: {:#?}", proc_net_ipv6_route);
|
||||
trace!("proc_net_route: {:#?}", proc_net_route);
|
||||
|
||||
// At least one routing table must be available
|
||||
if proc_net_ipv6_route.is_empty() && proc_net_route.is_empty() {
|
||||
return Err(Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
"No routing tables available",
|
||||
));
|
||||
}
|
||||
Ok(Self {
|
||||
proc_net_ipv6_route,
|
||||
proc_net_route,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn has_default_route(&self, name: &str) -> bool {
|
||||
for e in &self.proc_net_ipv6_route {
|
||||
if e.intf_name == name && e.dest_prefix == 0u8 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for e in &self.proc_net_route {
|
||||
if e.iface == name && e.mask == Ipv4Addr::new(0, 0, 0, 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn get_address_flags(&self, _addr: &IfAddr) -> AddressFlags {
|
||||
AddressFlags {
|
||||
is_temporary: false,
|
||||
is_dynamic: false,
|
||||
is_deprecated: false,
|
||||
}
|
||||
}
|
||||
}
|
216
veilid-core/src/intf/native/utils/network_interfaces/mod.rs
Normal file
216
veilid-core/src/intf/native/utils/network_interfaces/mod.rs
Normal file
@ -0,0 +1,216 @@
|
||||
use crate::xx::*;
|
||||
use crate::*;
|
||||
mod tools;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(target_os = "linux", target_os = "android"))] {
|
||||
mod netlink;
|
||||
use netlink::PlatformSupportNetlink as PlatformSupport;
|
||||
} else if #[cfg(target_os = "windows")] {
|
||||
mod windows;
|
||||
use windows::PlatformSupportWindows as PlatformSupport;
|
||||
} else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
|
||||
mod apple;
|
||||
use apple::PlatformSupportApple as PlatformSupport;
|
||||
} else {
|
||||
compile_error!("No network interfaces support for this platform!");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Clone)]
|
||||
pub enum IfAddr {
|
||||
V4(Ifv4Addr),
|
||||
V6(Ifv6Addr),
|
||||
}
|
||||
|
||||
impl IfAddr {
|
||||
pub fn ip(&self) -> IpAddr {
|
||||
match *self {
|
||||
IfAddr::V4(ref ifv4_addr) => IpAddr::V4(ifv4_addr.ip),
|
||||
IfAddr::V6(ref ifv6_addr) => IpAddr::V6(ifv6_addr.ip),
|
||||
}
|
||||
}
|
||||
pub fn netmask(&self) -> IpAddr {
|
||||
match *self {
|
||||
IfAddr::V4(ref ifv4_addr) => IpAddr::V4(ifv4_addr.netmask),
|
||||
IfAddr::V6(ref ifv6_addr) => IpAddr::V6(ifv6_addr.netmask),
|
||||
}
|
||||
}
|
||||
pub fn broadcast(&self) -> Option<IpAddr> {
|
||||
match *self {
|
||||
IfAddr::V4(ref ifv4_addr) => ifv4_addr.broadcast.map(IpAddr::V4),
|
||||
IfAddr::V6(ref ifv6_addr) => ifv6_addr.broadcast.map(IpAddr::V6),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Details about the ipv4 address of an interface on this host.
|
||||
#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Clone)]
|
||||
pub struct Ifv4Addr {
|
||||
/// The IP address of the interface.
|
||||
pub ip: Ipv4Addr,
|
||||
/// The netmask of the interface.
|
||||
pub netmask: Ipv4Addr,
|
||||
/// The broadcast address of the interface.
|
||||
pub broadcast: Option<Ipv4Addr>,
|
||||
}
|
||||
|
||||
/// Details about the ipv6 address of an interface on this host.
|
||||
#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Clone)]
|
||||
pub struct Ifv6Addr {
|
||||
/// The IP address of the interface.
|
||||
pub ip: Ipv6Addr,
|
||||
/// The netmask of the interface.
|
||||
pub netmask: Ipv6Addr,
|
||||
/// The broadcast address of the interface.
|
||||
pub broadcast: Option<Ipv6Addr>,
|
||||
}
|
||||
|
||||
/// Some of the flags associated with an interface.
|
||||
#[derive(Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||
pub struct InterfaceFlags {
|
||||
pub is_loopback: bool,
|
||||
pub is_running: bool,
|
||||
pub has_default_route: bool,
|
||||
}
|
||||
|
||||
/// Some of the flags associated with an address.
|
||||
#[derive(Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||
pub struct AddressFlags {
|
||||
pub is_temporary: bool,
|
||||
pub is_dynamic: bool,
|
||||
pub is_deprecated: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct InterfaceAddress {
|
||||
if_addr: IfAddr,
|
||||
flags: AddressFlags,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl InterfaceAddress {
|
||||
pub fn new(if_addr: IfAddr, flags: AddressFlags) -> Self {
|
||||
Self { if_addr, flags }
|
||||
}
|
||||
|
||||
pub fn if_addr(&self) -> &IfAddr {
|
||||
&self.if_addr
|
||||
}
|
||||
|
||||
pub fn is_temporary(&self) -> bool {
|
||||
self.flags.is_temporary
|
||||
}
|
||||
pub fn is_dynamic(&self) -> bool {
|
||||
self.flags.is_dynamic
|
||||
}
|
||||
pub fn is_deprecated(&self) -> bool {
|
||||
self.flags.is_deprecated
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct NetworkInterface {
|
||||
pub name: String,
|
||||
pub flags: InterfaceFlags,
|
||||
pub addrs: Vec<InterfaceAddress>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl NetworkInterface {
|
||||
pub fn new(name: String, flags: InterfaceFlags) -> Self {
|
||||
Self {
|
||||
name,
|
||||
flags,
|
||||
addrs: Vec::new(),
|
||||
}
|
||||
}
|
||||
pub fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
pub fn is_loopback(&self) -> bool {
|
||||
self.flags.is_loopback
|
||||
}
|
||||
|
||||
pub fn is_running(&self) -> bool {
|
||||
self.flags.is_running
|
||||
}
|
||||
|
||||
pub fn has_default_route(&self) -> bool {
|
||||
self.flags.has_default_route
|
||||
}
|
||||
|
||||
pub fn primary_ipv4(&self) -> Option<Ipv4Addr> {
|
||||
// see if we have a non-dynamic address to use first
|
||||
let mut best_dynamic: Option<Ipv4Addr> = None;
|
||||
for x in self.addrs.iter() {
|
||||
if let IfAddr::V4(a) = x.if_addr() {
|
||||
if !x.is_dynamic() {
|
||||
return Some(a.ip);
|
||||
} else if best_dynamic.is_none() {
|
||||
best_dynamic = Some(a.ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
best_dynamic
|
||||
}
|
||||
pub fn primary_ipv6(&self) -> Option<Ipv6Addr> {
|
||||
let mut best_dynamic: Option<Ipv6Addr> = None;
|
||||
for x in self.addrs.iter() {
|
||||
if let IfAddr::V6(a) = x.if_addr() {
|
||||
if x.is_temporary() || x.is_deprecated() {
|
||||
if !x.is_dynamic() {
|
||||
return Some(a.ip);
|
||||
} else if best_dynamic.is_none() {
|
||||
best_dynamic = Some(a.ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
best_dynamic
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct NetworkInterfaces {
|
||||
valid: bool,
|
||||
interfaces: BTreeMap<String, NetworkInterface>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl NetworkInterfaces {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
valid: false,
|
||||
interfaces: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.valid
|
||||
}
|
||||
pub fn clear(&mut self) {
|
||||
self.interfaces.clear();
|
||||
self.valid = false;
|
||||
}
|
||||
// returns Ok(false) if refresh had no changes, Ok(true) if changes were present
|
||||
pub async fn refresh(&mut self) -> Result<bool, String> {
|
||||
self.valid = false;
|
||||
|
||||
let last_interfaces = core::mem::take(&mut self.interfaces);
|
||||
|
||||
let mut platform_support = PlatformSupport::new().map_err(logthru_net!())?;
|
||||
platform_support
|
||||
.get_interfaces(&mut self.interfaces)
|
||||
.await?;
|
||||
|
||||
self.valid = true;
|
||||
|
||||
Ok(last_interfaces != self.interfaces)
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.interfaces.len()
|
||||
}
|
||||
pub fn iter(&self) -> std::collections::btree_map::Iter<String, NetworkInterface> {
|
||||
self.interfaces.iter()
|
||||
}
|
||||
}
|
288
veilid-core/src/intf/native/utils/network_interfaces/netlink.rs
Normal file
288
veilid-core/src/intf/native/utils/network_interfaces/netlink.rs
Normal file
@ -0,0 +1,288 @@
|
||||
use super::*;
|
||||
|
||||
use alloc::collections::btree_map::Entry;
|
||||
use futures_util::stream::TryStreamExt;
|
||||
use ifstructs::ifreq;
|
||||
use libc::{
|
||||
close, if_indextoname, ioctl, socket, IFA_F_DADFAILED, IFA_F_DEPRECATED, IFA_F_PERMANENT,
|
||||
IFA_F_TEMPORARY, IFA_F_TENTATIVE, IFF_LOOPBACK, IFF_RUNNING, IF_NAMESIZE, SIOCGIFFLAGS,
|
||||
SOCK_DGRAM,
|
||||
};
|
||||
use rtnetlink::packet::{nlas::address::Nla, AddressMessage, AF_INET, AF_INET6};
|
||||
use rtnetlink::{new_connection_with_socket, sys::SmolSocket, Handle, IpVersion};
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::CStr;
|
||||
use std::io;
|
||||
use std::os::raw::c_int;
|
||||
use tools::*;
|
||||
|
||||
fn get_interface_name(index: u32) -> Result<String, String> {
|
||||
let mut ifnamebuf = [0u8; (IF_NAMESIZE + 1)];
|
||||
if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr() as *mut i8) }.is_null() {
|
||||
return Err("if_indextoname returned null".to_owned());
|
||||
}
|
||||
let ifnamebuflen = ifnamebuf
|
||||
.iter()
|
||||
.position(|c| *c == 0u8)
|
||||
.ok_or_else(|| "null not found in interface name".to_owned())?;
|
||||
let ifname_str = CStr::from_bytes_with_nul(&ifnamebuf[0..=ifnamebuflen])
|
||||
.map_err(map_to_string)?
|
||||
.to_str()
|
||||
.map_err(map_to_string)?;
|
||||
Ok(ifname_str.to_owned())
|
||||
}
|
||||
|
||||
fn flags_to_address_flags(flags: u32) -> AddressFlags {
|
||||
AddressFlags {
|
||||
is_temporary: (flags & IFA_F_TEMPORARY) != 0,
|
||||
is_dynamic: (flags & IFA_F_PERMANENT) == 0,
|
||||
is_deprecated: (flags & IFA_F_DEPRECATED) != 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PlatformSupportNetlink {
|
||||
_connection_jh: intf::JoinHandle<()>,
|
||||
handle: Handle,
|
||||
default_route_interfaces: BTreeSet<u32>,
|
||||
}
|
||||
|
||||
impl PlatformSupportNetlink {
|
||||
pub fn new() -> Result<Self, String> {
|
||||
// Get the netlink connection
|
||||
let (connection, handle, _) = new_connection_with_socket::<SmolSocket>()
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!(error))?;
|
||||
|
||||
// Spawn a connection handler
|
||||
let _connection_jh = intf::spawn(connection);
|
||||
|
||||
Ok(PlatformSupportNetlink {
|
||||
_connection_jh,
|
||||
handle,
|
||||
default_route_interfaces: BTreeSet::new(),
|
||||
})
|
||||
}
|
||||
|
||||
// Figure out which interfaces have default routes
|
||||
async fn refresh_default_route_interfaces(&mut self) -> Result<(), String> {
|
||||
self.default_route_interfaces.clear();
|
||||
let mut routesv4 = self.handle.route().get(IpVersion::V4).execute();
|
||||
while let Some(routev4) = routesv4.try_next().await.unwrap_or_default() {
|
||||
if let Some(index) = routev4.input_interface() {
|
||||
if let Some((dest, prefix)) = routev4.destination_prefix() {
|
||||
if prefix == 0 && dest.is_unspecified() {
|
||||
self.default_route_interfaces.insert(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut routesv6 = self.handle.route().get(IpVersion::V6).execute();
|
||||
while let Some(routev6) = routesv6.try_next().await.unwrap_or_default() {
|
||||
if let Some(index) = routev6.input_interface() {
|
||||
if let Some((dest, prefix)) = routev6.destination_prefix() {
|
||||
if prefix == 0 && dest.is_unspecified() {
|
||||
self.default_route_interfaces.insert(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_interface_flags(&self, index: u32, ifname: &str) -> Result<InterfaceFlags, String> {
|
||||
let mut req = ifreq::from_name(ifname).map_err(map_to_string)?;
|
||||
|
||||
let sock = unsafe { socket(AF_INET as i32, SOCK_DGRAM, 0) };
|
||||
if sock < 0 {
|
||||
return Err(io::Error::last_os_error()).map_err(map_to_string);
|
||||
}
|
||||
|
||||
let res = unsafe { ioctl(sock, SIOCGIFFLAGS, &mut req) };
|
||||
unsafe { close(sock) };
|
||||
if res < 0 {
|
||||
return Err(io::Error::last_os_error()).map_err(map_to_string);
|
||||
}
|
||||
|
||||
let flags = req.get_flags() as c_int;
|
||||
|
||||
Ok(InterfaceFlags {
|
||||
is_loopback: (flags & IFF_LOOPBACK) != 0,
|
||||
is_running: (flags & IFF_RUNNING) != 0,
|
||||
has_default_route: self.default_route_interfaces.contains(&index),
|
||||
})
|
||||
}
|
||||
|
||||
fn process_address_message_v4(msg: AddressMessage) -> Option<InterfaceAddress> {
|
||||
// Get ip address
|
||||
let ip = msg.nlas.iter().find_map(|nla| {
|
||||
if let Nla::Address(a) = nla {
|
||||
let a: Option<[u8; 4]> = a.clone().try_into().ok();
|
||||
a.map(Ipv4Addr::from)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})?;
|
||||
|
||||
// get netmask
|
||||
let plen = msg.header.prefix_len as i16;
|
||||
let mut netmask = [0u8; 4];
|
||||
get_netmask_from_prefix_length_v4(&mut netmask, plen);
|
||||
let netmask = Ipv4Addr::from(netmask);
|
||||
|
||||
// get broadcast address
|
||||
let broadcast = msg.nlas.iter().find_map(|nla| {
|
||||
if let Nla::Broadcast(b) = nla {
|
||||
let b: Option<[u8; 4]> = b.clone().try_into().ok();
|
||||
b.map(Ipv4Addr::from)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
// get address flags
|
||||
let flags = msg
|
||||
.nlas
|
||||
.iter()
|
||||
.find_map(|nla| {
|
||||
if let Nla::Flags(f) = nla {
|
||||
Some(*f)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or(msg.header.flags as u32);
|
||||
|
||||
Some(InterfaceAddress::new(
|
||||
IfAddr::V4(Ifv4Addr {
|
||||
ip,
|
||||
/// The netmask of the interface.
|
||||
netmask,
|
||||
/// The broadcast address of the interface.
|
||||
broadcast,
|
||||
}),
|
||||
flags_to_address_flags(flags),
|
||||
))
|
||||
}
|
||||
|
||||
fn process_address_message_v6(msg: AddressMessage) -> Option<InterfaceAddress> {
|
||||
// Get ip address
|
||||
let ip = msg.nlas.iter().find_map(|nla| {
|
||||
if let Nla::Address(a) = nla {
|
||||
let a: Option<[u8; 16]> = a.clone().try_into().ok();
|
||||
a.map(Ipv6Addr::from)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})?;
|
||||
|
||||
// get netmask
|
||||
let plen = msg.header.prefix_len as i16;
|
||||
let mut netmask = [0u8; 16];
|
||||
get_netmask_from_prefix_length_v6(&mut netmask, plen);
|
||||
let netmask = Ipv6Addr::from(netmask);
|
||||
|
||||
// get address flags
|
||||
let flags = msg
|
||||
.nlas
|
||||
.iter()
|
||||
.find_map(|nla| {
|
||||
if let Nla::Flags(f) = nla {
|
||||
Some(*f)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or(msg.header.flags as u32);
|
||||
|
||||
// Skip addresses going through duplicate address detection, or ones that have failed it
|
||||
if ((flags & IFA_F_TENTATIVE) != 0) || ((flags & IFA_F_DADFAILED) != 0) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(InterfaceAddress::new(
|
||||
IfAddr::V6(Ifv6Addr {
|
||||
ip,
|
||||
/// The netmask of the interface.
|
||||
netmask,
|
||||
/// The broadcast address of the interface.
|
||||
broadcast: None,
|
||||
}),
|
||||
flags_to_address_flags(flags),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn get_interfaces(
|
||||
&mut self,
|
||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||
) -> Result<(), String> {
|
||||
// Refresh the routes
|
||||
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());
|
||||
}
|
||||
|
||||
// Ask for all the addresses we have
|
||||
let mut names = BTreeMap::<u32, String>::new();
|
||||
let mut addresses = self.handle.address().get().execute();
|
||||
while let Some(msg) = addresses
|
||||
.try_next()
|
||||
.await
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!(error))?
|
||||
{
|
||||
// Have we seen this interface index yet?
|
||||
// Get the name from the index, cached, if we can
|
||||
let ifname = match names.entry(msg.header.index) {
|
||||
Entry::Vacant(v) => {
|
||||
// If not, get the name for the index if we can
|
||||
let ifname = match get_interface_name(msg.header.index) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
log_net!(
|
||||
"couldn't get interface name for index {}: {}",
|
||||
msg.header.index,
|
||||
e
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
v.insert(ifname).clone()
|
||||
}
|
||||
Entry::Occupied(o) => o.get().clone(),
|
||||
};
|
||||
|
||||
// Map the name to a NetworkInterface
|
||||
if !interfaces.contains_key(&ifname) {
|
||||
// If we have no NetworkInterface yet, make one
|
||||
let flags = self.get_interface_flags(msg.header.index, &ifname)?;
|
||||
interfaces.insert(ifname.clone(), NetworkInterface::new(ifname.clone(), flags));
|
||||
}
|
||||
let intf = interfaces.get_mut(&ifname).unwrap();
|
||||
|
||||
// Process the address
|
||||
let intf_addr = match msg.header.family as u16 {
|
||||
AF_INET => match Self::process_address_message_v4(msg) {
|
||||
Some(ia) => ia,
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
},
|
||||
AF_INET6 => match Self::process_address_message_v6(msg) {
|
||||
Some(ia) => ia,
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
intf.addrs.push(intf_addr);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
pub fn convert_to_unsigned_4(x: [i8; 4]) -> [u8; 4] {
|
||||
let mut out: [u8; 4] = [0u8; 4];
|
||||
for i in 0..4 {
|
||||
out[i] = x[i] as u8;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
pub fn convert_to_unsigned_16(x: [i8; 16]) -> [u8; 16] {
|
||||
let mut out: [u8; 16] = [0u8; 16];
|
||||
for i in 0..16 {
|
||||
out[i] = x[i] as u8;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
pub fn get_netmask_from_prefix_length_v4(out: &mut [u8; 4], mut plen: i16) {
|
||||
for outb in out.iter_mut() {
|
||||
*outb = if plen >= 8 {
|
||||
plen -= 8;
|
||||
255u8
|
||||
} else if plen <= 0 {
|
||||
0u8
|
||||
} else {
|
||||
let v = 255u8 << (8 - plen);
|
||||
plen = 0;
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_netmask_from_prefix_length_v6(out: &mut [u8; 16], mut plen: i16) {
|
||||
for outb in out.iter_mut() {
|
||||
*outb = if plen >= 8 {
|
||||
plen -= 8;
|
||||
255u8
|
||||
} else if plen == 0 {
|
||||
0u8
|
||||
} else {
|
||||
let v = 255u8 << (8 - plen);
|
||||
plen = 0;
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
use super::*;
|
||||
|
||||
pub struct PlatformSupportWindows {
|
||||
//
|
||||
}
|
||||
|
||||
impl PlatformSupportWindows {
|
||||
pub fn new() -> Result<Self, String> {
|
||||
Ok(PlatformSupportWindows {})
|
||||
}
|
||||
|
||||
pub async fn get_interfaces(
|
||||
&mut self,
|
||||
interfaces: &mut BTreeMap<String, NetworkInterface>,
|
||||
) -> Result<(), String> {
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -80,6 +80,7 @@ impl TableStore {
|
||||
let db = Database::open(table_name.clone(), column_count)
|
||||
.await
|
||||
.map_err(|e| format!("failed to open tabledb at: {} ({})", table_name, e))?;
|
||||
info!("opened table store '{}' with table name '{:?}' with {} columns", name, table_name, column_count);
|
||||
|
||||
let table_db = TableDB::new(table_name.clone(), self.clone(), db);
|
||||
|
||||
|
@ -8,7 +8,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.veilid.veilidcore.veilidcore_android_tests"
|
||||
minSdkVersion 23
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 30
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
@ -61,9 +61,10 @@ dependencies {
|
||||
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
|
||||
|
||||
cargo {
|
||||
module = "../../../.."
|
||||
module = "../../../../../veilid-core"
|
||||
libname = "veilid_core"
|
||||
targets = ["arm64", "x86", "x86_64"]
|
||||
targetDirectory = "../../../../../target"
|
||||
prebuiltToolchains = true
|
||||
profile = gradle.startParameter.taskNames.any{it.toLowerCase().contains("debug")} ? "debug" : "release"
|
||||
features {
|
||||
|
@ -13,7 +13,7 @@ buildscript {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "org.mozilla.rust-android-gradle.rust-android" version "0.8.6"
|
||||
id "org.mozilla.rust-android-gradle.rust-android" version "0.9.0"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
|
@ -542,13 +542,14 @@ cfg_if! {
|
||||
let mut interfaces = intf::utils::network_interfaces::NetworkInterfaces::new();
|
||||
let count = 100;
|
||||
for _ in 0..count {
|
||||
if let Err(e) = interfaces.refresh() {
|
||||
if let Err(e) = interfaces.refresh().await {
|
||||
error!("error refreshing interfaces: {}", e);
|
||||
}
|
||||
}
|
||||
let t2 = intf::get_timestamp();
|
||||
let tdiff = ((t2 - t1) as f64)/1000000.0f64;
|
||||
info!("running network interface test with {} iterations took {} seconds", count, tdiff);
|
||||
info!("interfaces: {:#?}", interfaces)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +125,8 @@ cfg_if! {
|
||||
cb.add_filter_ignore_str("async_std");
|
||||
cb.add_filter_ignore_str("async_io");
|
||||
cb.add_filter_ignore_str("polling");
|
||||
cb.add_filter_ignore_str("netlink_proto");
|
||||
cb.add_filter_ignore_str("netlink_sys");
|
||||
TestLogger::init(LevelFilter::Trace, cb.build()).unwrap();
|
||||
});
|
||||
}
|
||||
|
@ -196,6 +196,7 @@ pub async fn main() -> Result<(), String> {
|
||||
cb.add_filter_ignore_str("rustls");
|
||||
cb.add_filter_ignore_str("async_tungstenite");
|
||||
cb.add_filter_ignore_str("tungstenite");
|
||||
cb.add_filter_ignore_str("netlink_proto");
|
||||
|
||||
if settingsr.logging.terminal.enabled {
|
||||
logs.push(TermLogger::new(
|
||||
|
Loading…
Reference in New Issue
Block a user