use get_if_addrs::{self, IfAddr};
use priv_prelude::*;
pub trait IpAddrExt {
fn is_global(&self) -> bool;
fn is_private(&self) -> bool;
fn expand_local_unspecified(&self) -> io::Result<Vec<IpAddr>>;
fn unspecified_to_localhost(&self) -> IpAddr;
}
impl IpAddrExt for IpAddr {
fn is_global(&self) -> bool {
match *self {
IpAddr::V4(ref ip) => Ipv4AddrExt::is_global(ip),
IpAddr::V6(ref ip) => Ipv6AddrExt::is_global(ip),
}
}
fn is_private(&self) -> bool {
match *self {
IpAddr::V4(ref ip) => ip.is_private(),
IpAddr::V6(_) => false,
}
}
fn expand_local_unspecified(&self) -> io::Result<Vec<IpAddr>> {
let ret = match *self {
IpAddr::V4(v4_addr) => v4_addr
.expand_local_unspecified()?
.into_iter()
.map(IpAddr::V4)
.collect(),
IpAddr::V6(v6_addr) => v6_addr
.expand_local_unspecified()?
.into_iter()
.map(IpAddr::V6)
.collect(),
};
Ok(ret)
}
fn unspecified_to_localhost(&self) -> IpAddr {
match *self {
IpAddr::V4(ref ip) => IpAddr::V4(ip.unspecified_to_localhost()),
IpAddr::V6(ref ip) => IpAddr::V6(ip.unspecified_to_localhost()),
}
}
}
pub trait Ipv4AddrExt {
fn is_global(&self) -> bool;
fn expand_local_unspecified(&self) -> io::Result<Vec<Ipv4Addr>>;
fn unspecified_to_localhost(&self) -> Ipv4Addr;
}
pub trait Ipv6AddrExt {
fn is_global(&self) -> bool;
fn expand_local_unspecified(&self) -> io::Result<Vec<Ipv6Addr>>;
fn unspecified_to_localhost(&self) -> Ipv6Addr;
}
impl Ipv4AddrExt for Ipv4Addr {
fn is_global(&self) -> bool {
!self.is_private()
&& !self.is_loopback()
&& !self.is_link_local()
&& !self.is_broadcast()
&& !self.is_documentation()
&& !self.is_unspecified()
}
fn expand_local_unspecified(&self) -> io::Result<Vec<Ipv4Addr>> {
if !self.is_unspecified() {
return Ok(vec![*self]);
}
let mut ret = Vec::new();
let ifs = get_if_addrs::get_if_addrs()?;
for interface in ifs {
if let IfAddr::V4(v4_addr) = interface.addr {
ret.push(v4_addr.ip);
}
}
Ok(ret)
}
fn unspecified_to_localhost(&self) -> Ipv4Addr {
if self.is_unspecified() {
ipv4!("127.0.0.1")
} else {
*self
}
}
}
impl Ipv6AddrExt for Ipv6Addr {
fn is_global(&self) -> bool {
!self.is_loopback() && !self.is_unspecified()
}
fn expand_local_unspecified(&self) -> io::Result<Vec<Ipv6Addr>> {
if !self.is_unspecified() {
return Ok(vec![*self]);
}
let mut ret = Vec::new();
let ifs = get_if_addrs::get_if_addrs()?;
for interface in ifs {
if let IfAddr::V6(v6_addr) = interface.addr {
ret.push(v6_addr.ip);
}
}
Ok(ret)
}
fn unspecified_to_localhost(&self) -> Ipv6Addr {
if self.is_unspecified() {
ipv6!("::1")
} else {
*self
}
}
}