android fixes

This commit is contained in:
John Smith 2022-01-06 08:41:36 -05:00
parent ffe0a42dd3
commit e412e47474
6 changed files with 148 additions and 44 deletions

3
.gitmodules vendored
View File

@ -13,3 +13,6 @@
[submodule "external/keyvaluedb"]
path = external/keyvaluedb
url = ../keyvaluedb.git
[submodule "external/netlink"]
path = external/netlink
url = git@gitlab.hackers.town:veilid/netlink.git

12
Cargo.lock generated
View File

@ -2126,8 +2126,6 @@ dependencies = [
[[package]]
name = "netlink-packet-core"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8349128e95f5dabcb8a18587ad06b3ca7993e90c0c360b4a2abac0313ebce727"
dependencies = [
"anyhow",
"byteorder",
@ -2138,8 +2136,6 @@ dependencies = [
[[package]]
name = "netlink-packet-route"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb5d54077de7c0904111e1d19b661b8cfccbc23d9ce5b6dbcc7362721e6e552"
dependencies = [
"anyhow",
"bitflags",
@ -2152,8 +2148,6 @@ dependencies = [
[[package]]
name = "netlink-packet-utils"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a008a56eceb0cab06739c7f37f15bda27f1147a14d0e7136e8c913b94f1441d"
dependencies = [
"anyhow",
"byteorder",
@ -2164,8 +2158,6 @@ dependencies = [
[[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",
@ -2178,8 +2170,6 @@ dependencies = [
[[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",
@ -2938,8 +2928,6 @@ dependencies = [
[[package]]
name = "rtnetlink"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa584f57f271d3fbd9f59503b090a0410a531c8cc272143669bf136c62ef409d"
dependencies = [
"async-global-executor",
"futures",

View File

@ -12,6 +12,19 @@ exclude = [ "./external/cursive" ]
cursive = { path = "./external/cursive/cursive" }
cursive_core = { path = "./external/cursive/cursive-core" }
netlink-sys = { path = "./external/netlink/netlink-sys" }
netlink-packet-core = { path = "./external/netlink/netlink-packet-core" }
netlink-packet-utils = { path = "./external/netlink/netlink-packet-utils" }
#netlink-packet-generic = { path = "./external/netlink/netlink-packet-generic" }
netlink-packet-route = { path = "./external/netlink/netlink-packet-route" }
#netlink-packet-audit = { path = "./external/netlink/netlink-packet-audit" }
#netlink-packet-sock-diag = { path = "./external/netlink/netlink-packet-sock-diag" }
netlink-proto = { path = "./external/netlink/netlink-proto" }
#genetlink = { path = "./external/netlink/genetlink" }
rtnetlink = { path = "./external/netlink/rtnetlink" }
#audit = { path = "./external/netlink/audit" }
#ethtool = { path = "./external/netlink/ethtool" }
[profile.release]
opt-level = "s"
lto = true

1
external/netlink vendored Submodule

@ -0,0 +1 @@
Subproject commit bf542d210ec3c3f1c359b49036dc938ddfb3fdf9

View File

@ -79,8 +79,10 @@ pub struct InterfaceFlags {
/// 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,
// common flags
pub is_dynamic: bool,
// ipv6 flags
pub is_temporary: bool,
pub is_deprecated: bool,
}
@ -90,6 +92,84 @@ pub struct InterfaceAddress {
flags: AddressFlags,
}
use core::cmp::Ordering;
impl Ord for InterfaceAddress {
fn cmp(&self, other: &Self) -> Ordering {
match (&self.if_addr, &other.if_addr) {
(IfAddr::V4(a), IfAddr::V4(b)) => {
// global scope addresses are better
let ret = ipv4addr_is_global(&a.ip).cmp(&ipv4addr_is_global(&b.ip));
if ret != Ordering::Equal {
return ret;
}
// local scope addresses are better
let ret = ipv4addr_is_private(&a.ip).cmp(&ipv4addr_is_private(&b.ip));
if ret != Ordering::Equal {
return ret;
}
// non-dynamic addresses are better
let ret = (!self.flags.is_dynamic).cmp(&!other.flags.is_dynamic);
if ret != Ordering::Equal {
return ret;
}
}
(IfAddr::V6(a), IfAddr::V6(b)) => {
// non-deprecated addresses are better
let ret = (!self.flags.is_deprecated).cmp(&!other.flags.is_deprecated);
if ret != Ordering::Equal {
return ret;
}
// non-temporary address are better
let ret = (!self.flags.is_temporary).cmp(&!other.flags.is_temporary);
if ret != Ordering::Equal {
return ret;
}
// global scope addresses are better
let ret = ipv6addr_is_global(&a.ip).cmp(&ipv6addr_is_global(&b.ip));
if ret != Ordering::Equal {
return ret;
}
// unique local unicast addresses are better
let ret = ipv6addr_is_unique_local(&a.ip).cmp(&ipv6addr_is_unique_local(&b.ip));
if ret != Ordering::Equal {
return ret;
}
// unicast site local addresses are better
let ret = ipv6addr_is_unicast_site_local(&a.ip)
.cmp(&ipv6addr_is_unicast_site_local(&b.ip));
if ret != Ordering::Equal {
return ret;
}
// unicast link local addresses are better
let ret = ipv6addr_is_unicast_link_local(&a.ip)
.cmp(&ipv6addr_is_unicast_link_local(&b.ip));
if ret != Ordering::Equal {
return ret;
}
// non-dynamic addresses are better
let ret = (!self.flags.is_dynamic).cmp(&!other.flags.is_dynamic);
if ret != Ordering::Equal {
return ret;
}
}
(IfAddr::V4(_), IfAddr::V6(_)) => return Ordering::Less,
(IfAddr::V6(_), IfAddr::V4(_)) => return Ordering::Greater,
}
// stable sort
let ret = self.if_addr.cmp(&other.if_addr);
if ret != Ordering::Equal {
return ret;
}
self.flags.cmp(&other.flags)
}
}
impl PartialOrd for InterfaceAddress {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[allow(dead_code)]
impl InterfaceAddress {
pub fn new(if_addr: IfAddr, flags: AddressFlags) -> Self {
@ -158,33 +238,35 @@ impl NetworkInterface {
}
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
let mut ipv4addrs: Vec<&InterfaceAddress> = self
.addrs
.iter()
.filter(|a| matches!(a.if_addr(), IfAddr::V4(_)))
.collect();
ipv4addrs.sort();
ipv4addrs
.last()
.map(|x| match x.if_addr() {
IfAddr::V4(v4) => Some(v4.ip),
_ => None,
})
.flatten()
}
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
let mut ipv6addrs: Vec<&InterfaceAddress> = self
.addrs
.iter()
.filter(|a| matches!(a.if_addr(), IfAddr::V6(_)))
.collect();
ipv6addrs.sort();
ipv6addrs
.last()
.map(|x| match x.if_addr() {
IfAddr::V6(v6) => Some(v6.ip),
_ => None,
})
.flatten()
}
}

View File

@ -4,11 +4,13 @@ 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,
close, if_indextoname, ioctl, socket, IFF_LOOPBACK, IFF_RUNNING, IF_NAMESIZE, SIOCGIFFLAGS,
SOCK_DGRAM,
};
use rtnetlink::packet::{nlas::address::Nla, AddressMessage, AF_INET, AF_INET6};
use rtnetlink::packet::{
nlas::address::Nla, AddressMessage, AF_INET, AF_INET6, IFA_F_DADFAILED, IFA_F_DEPRECATED,
IFA_F_PERMANENT, IFA_F_TEMPORARY, IFA_F_TENTATIVE,
};
use rtnetlink::{new_connection_with_socket, sys::SmolSocket, Handle, IpVersion};
use std::convert::TryInto;
use std::ffi::CStr;
@ -18,9 +20,18 @@ use tools::*;
fn get_interface_name(index: u32) -> Result<String, String> {
let mut ifnamebuf = [0u8; (IF_NAMESIZE + 1)];
cfg_if! {
if #[cfg(all(target_os = "android", target_arch = "aarch64"))] {
if unsafe { if_indextoname(index, ifnamebuf.as_mut_ptr()) }.is_null() {
return Err("if_indextoname returned null".to_owned());
}
} else {
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)
@ -95,7 +106,13 @@ impl PlatformSupportNetlink {
return Err(io::Error::last_os_error()).map_err(map_to_string);
}
cfg_if! {
if #[cfg(target_os = "android")] {
let res = unsafe { ioctl(sock, SIOCGIFFLAGS as i32, &mut req) };
} else {
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);