use std::{
io,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
};
use hardware_address::MacAddr;
use smallvec_wrapper::{SmallVec, TinyVec};
use smol_str::SmolStr;
use super::{
ifname_to_index, ipv4_filter_to_ip_filter, ipv6_filter_to_ip_filter, os, Flags, IfNet, Ifv4Net,
Ifv6Net,
};
#[cfg(any(
target_vendor = "apple",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "linux",
windows
))]
use super::{IfAddr, Ifv4Addr, Ifv6Addr};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Interface {
pub(super) index: u32,
pub(super) mtu: u32,
pub(super) name: SmolStr,
pub(super) mac_addr: Option<MacAddr>,
pub(super) flags: Flags,
}
impl Interface {
#[inline]
pub const fn index(&self) -> u32 {
self.index
}
#[inline]
pub const fn name(&self) -> &SmolStr {
&self.name
}
#[inline]
pub const fn mtu(&self) -> u32 {
self.mtu
}
#[inline]
pub const fn mac_addr(&self) -> Option<MacAddr> {
self.mac_addr
}
#[inline]
pub const fn flags(&self) -> Flags {
self.flags
}
#[inline]
pub fn addrs(&self) -> io::Result<SmallVec<IfNet>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_addresses(Some(self.index), |_| true)
} else {
os::interface_addresses(self.index, |_| true)
}
}
}
#[inline]
pub fn addrs_by_filter<F>(&self, f: F) -> io::Result<SmallVec<IfNet>>
where
F: FnMut(&IpAddr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_addresses(Some(self.index), f)
} else {
os::interface_addresses(self.index, f)
}
}
}
#[inline]
pub fn ipv4_addrs(&self) -> io::Result<SmallVec<Ifv4Net>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_ipv4_addresses(Some(self.index), |_| true)
} else {
os::interface_ipv4_addresses(self.index, |_| true)
}
}
}
#[inline]
pub fn ipv4_addrs_by_filter<F>(&self, f: F) -> io::Result<SmallVec<Ifv4Net>>
where
F: FnMut(&Ipv4Addr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_ipv4_addresses(Some(self.index), ipv4_filter_to_ip_filter(f))
} else {
os::interface_ipv4_addresses(self.index, ipv4_filter_to_ip_filter(f))
}
}
}
#[inline]
pub fn ipv6_addrs(&self) -> io::Result<SmallVec<Ifv6Net>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_ipv6_addresses(Some(self.index), |_| true)
} else {
os::interface_ipv6_addresses(self.index, |_| true)
}
}
}
#[inline]
pub fn ipv6_addrs_by_filter<F>(&self, f: F) -> io::Result<SmallVec<Ifv6Net>>
where
F: FnMut(&Ipv6Addr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_ipv6_addresses(Some(self.index), ipv6_filter_to_ip_filter(f))
} else {
os::interface_ipv6_addresses(self.index, ipv6_filter_to_ip_filter(f))
}
}
}
cfg_multicast!(
pub fn multicast_addrs(&self) -> io::Result<SmallVec<IfAddr>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_addresses(Some(self.index), |_| true)
} else {
os::interface_multicast_addresses(self.index, |_| true)
}
}
}
pub fn multicast_addrs_by_filter<F>(&self, f: F) -> io::Result<SmallVec<IfAddr>>
where
F: FnMut(&IpAddr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_addresses(Some(self.index), f)
} else {
os::interface_multicast_addresses(self.index, f)
}
}
}
pub fn ipv4_multicast_addrs(&self) -> io::Result<SmallVec<Ifv4Addr>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_ipv4_addresses(Some(self.index), |_| true)
} else {
os::interface_multicast_ipv4_addresses(self.index, |_| true)
}
}
}
pub fn ipv4_multicast_addrs_by_filter<F>(&self, f: F) -> io::Result<SmallVec<Ifv4Addr>>
where
F: FnMut(&Ipv4Addr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_ipv4_addresses(Some(self.index), f)
} else {
os::interface_multicast_ipv4_addresses(self.index, f)
}
}
}
pub fn ipv6_multicast_addrs(&self) -> io::Result<SmallVec<Ifv6Addr>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_ipv6_addresses(Some(self.index), |_| true)
} else {
os::interface_multicast_ipv6_addresses(self.index, |_| true)
}
}
}
pub fn ipv6_multicast_addrs_by_filter<F>(&self, f: F) -> io::Result<SmallVec<Ifv6Addr>>
where
F: FnMut(&Ipv6Addr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_ipv6_addresses(Some(self.index), f)
} else {
os::interface_multicast_ipv6_addresses(self.index, f)
}
}
}
);
}
pub fn interfaces() -> io::Result<TinyVec<Interface>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_table(None)
} else {
os::interface_table(0)
}
}
}
pub fn interface_by_index(index: u32) -> io::Result<Option<Interface>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_table(Some(index)).map(|v| v.into_iter().find(|ifi| ifi.index == index))
} else {
os::interface_table(index).map(|v| v.into_iter().find(|ifi| ifi.index == index))
}
}
}
pub fn interface_by_name(name: &str) -> io::Result<Option<Interface>> {
let idx = ifname_to_index(name)?;
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_table(Some(idx)).map(|v| v.into_iter().find(|ifi| ifi.index == idx))
} else {
os::interface_table(idx).map(|v| v.into_iter().find(|ifi| ifi.name == name))
}
}
}
pub fn interface_addrs() -> io::Result<SmallVec<IfNet>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_addresses(None, |_| true)
} else {
os::interface_addresses(0, |_| true)
}
}
}
pub fn interface_ipv4_addrs() -> io::Result<SmallVec<Ifv4Net>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_ipv4_addresses(None, |_| true)
} else {
os::interface_ipv4_addresses(0, |_| true)
}
}
}
pub fn interface_ipv6_addrs() -> io::Result<SmallVec<Ifv6Net>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_ipv6_addresses(None, |_| true)
} else {
os::interface_ipv6_addresses(0, |_| true)
}
}
}
pub fn interface_addrs_by_filter<F>(f: F) -> io::Result<SmallVec<IfNet>>
where
F: FnMut(&IpAddr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_addresses(None, f)
} else {
os::interface_addresses(0, f)
}
}
}
pub fn interface_ipv4_addrs_by_filter<F>(f: F) -> io::Result<SmallVec<Ifv4Net>>
where
F: FnMut(&Ipv4Addr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_ipv4_addresses(None, ipv4_filter_to_ip_filter(f))
} else {
os::interface_ipv4_addresses(0, ipv4_filter_to_ip_filter(f))
}
}
}
pub fn interface_ipv6_addrs_by_filter<F>(f: F) -> io::Result<SmallVec<Ifv6Net>>
where
F: FnMut(&Ipv6Addr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_ipv6_addresses(None, ipv6_filter_to_ip_filter(f))
} else {
os::interface_ipv6_addresses(0, ipv6_filter_to_ip_filter(f))
}
}
}
cfg_multicast!(
pub fn interface_multicast_addrs() -> io::Result<SmallVec<IfAddr>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_addresses(None, |_| true)
} else {
os::interface_multicast_addresses(0, |_| true)
}
}
}
pub fn interface_multicast_addrs_by_filter<F>(f: F) -> io::Result<SmallVec<IfAddr>>
where
F: FnMut(&IpAddr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_addresses(None, f)
} else {
os::interface_multicast_addresses(0, f)
}
}
}
pub fn interface_multicast_ipv4_addrs() -> io::Result<SmallVec<Ifv4Addr>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_ipv4_addresses(None, |_| true)
} else {
os::interface_multicast_ipv4_addresses(0, |_| true)
}
}
}
pub fn interface_multicast_ipv4_addrs_by_filter<F>(f: F) -> io::Result<SmallVec<Ifv4Addr>>
where
F: FnMut(&Ipv4Addr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_ipv4_addresses(None, f)
} else {
os::interface_multicast_ipv4_addresses(0, f)
}
}
}
pub fn interface_multicast_ipv6_addrs() -> io::Result<SmallVec<Ifv6Addr>> {
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_ipv6_addresses(None, |_| true)
} else {
os::interface_multicast_ipv6_addresses(0, |_| true)
}
}
}
pub fn interface_multicast_ipv6_addrs_by_filter<F>(f: F) -> io::Result<SmallVec<Ifv6Addr>>
where
F: FnMut(&Ipv6Addr) -> bool,
{
cfg_if::cfg_if! {
if #[cfg(windows)] {
os::interface_multicast_ipv6_addresses(None, f)
} else {
os::interface_multicast_ipv6_addresses(0, f)
}
}
}
);