getifs 0.6.0

Cross-platform enumeration of network interfaces and their MTU, gateway, multicast, and local/private/public IP addresses.
Documentation
use std::{
  io,
  net::{IpAddr, Ipv4Addr, Ipv6Addr},
};

use smallvec_wrapper::SmallVec;

use super::{os, IfNet, Ifv4Net, Ifv6Net};

/// Returns all non-loopback IPv4 addresses configured on every
/// interface on the system.
///
/// This enumerates all interface addresses and applies a
/// loopback/link-local filter — it does **not** check whether the
/// owning interface has a usable route. For a route-aware variant that
/// returns only the addresses of the best-default-route interface,
/// see [`best_local_ipv4_addrs`].
///
/// See also [`local_ipv4_addrs_by_filter`].
///
/// ## Example
///
/// ```rust
/// use getifs::local_ipv4_addrs;
///
/// let ipv4_addrs = local_ipv4_addrs().unwrap();
/// for addr in ipv4_addrs {
///   println!("{addr}");
/// }
/// ```
pub fn local_ipv4_addrs() -> io::Result<SmallVec<Ifv4Net>> {
  os::local_ipv4_addrs()
}

/// Returns all non-loopback IPv6 addresses configured on every
/// interface on the system.
///
/// This enumerates all interface addresses and applies a
/// loopback/link-local filter — it does **not** check whether the
/// owning interface has a usable route. For a route-aware variant
/// that returns only the addresses of the best-default-route
/// interface, see [`best_local_ipv6_addrs`].
///
/// See also [`local_ipv6_addrs_by_filter`].
///
/// ## Example
///
/// ```rust
/// use getifs::local_ipv6_addrs;
///
/// let ipv6_addrs = local_ipv6_addrs().unwrap();
/// for addr in ipv6_addrs {
///   println!("{addr}");
/// }
/// ```
pub fn local_ipv6_addrs() -> io::Result<SmallVec<Ifv6Net>> {
  os::local_ipv6_addrs()
}

/// Returns all non-loopback IP addresses (both IPv4 and IPv6)
/// configured on every interface on the system.
///
/// This enumerates all interface addresses and applies a
/// loopback/link-local filter — it does **not** check whether the
/// owning interface has a usable route. For a route-aware variant
/// that returns only the addresses of the best-default-route
/// interface, see [`best_local_addrs`].
///
/// See also [`local_addrs_by_filter`].
///
/// ## Example
///
/// ```rust
/// use getifs::local_addrs;
///
/// let all_addrs = local_addrs().unwrap();
/// for addr in all_addrs {
///   println!("{addr}");
/// }
/// ```
pub fn local_addrs() -> io::Result<SmallVec<IfNet>> {
  os::local_addrs()
}

/// Returns all non-loopback IPv4 addresses configured on every
/// interface on the system, further refined by the provided filter.
///
/// Like [`local_ipv4_addrs`], this does **not** check whether the
/// owning interface has a usable route — see [`best_local_ipv4_addrs`]
/// for the route-aware variant.
///
/// ## Example
///
/// ```rust
/// use getifs::local_ipv4_addrs_by_filter;
///
/// let addrs = local_ipv4_addrs_by_filter(|addr| !addr.is_loopback()).unwrap();
/// for addr in addrs {
///   println!("{addr}");
/// }
/// ```
pub fn local_ipv4_addrs_by_filter<F>(f: F) -> io::Result<SmallVec<Ifv4Net>>
where
  F: FnMut(&Ipv4Addr) -> bool,
{
  os::local_ipv4_addrs_by_filter(f)
}

/// Returns all non-loopback IPv6 addresses configured on every
/// interface on the system, further refined by the provided filter.
///
/// Like [`local_ipv6_addrs`], this does **not** check whether the
/// owning interface has a usable route — see [`best_local_ipv6_addrs`]
/// for the route-aware variant.
///
/// ## Example
///
/// ```rust
/// use getifs::local_ipv6_addrs_by_filter;
///
/// let addrs = local_ipv6_addrs_by_filter(|addr| !addr.is_loopback()).unwrap();
/// for addr in addrs {
///   println!("{addr}");
/// }
/// ```
pub fn local_ipv6_addrs_by_filter<F>(f: F) -> io::Result<SmallVec<Ifv6Net>>
where
  F: FnMut(&Ipv6Addr) -> bool,
{
  os::local_ipv6_addrs_by_filter(f)
}

/// Returns all non-loopback IP addresses (both IPv4 and IPv6)
/// configured on every interface on the system, further refined by
/// the provided filter.
///
/// Like [`local_addrs`], this does **not** check whether the owning
/// interface has a usable route — see [`best_local_addrs`] for the
/// route-aware variant.
///
/// ## Example
///
/// ```rust
/// use getifs::local_addrs_by_filter;
///
///
/// let addrs = local_addrs_by_filter(|addr| !addr.is_loopback()).unwrap();
/// for addr in addrs {
///   println!("{addr}");
/// }
/// ```
pub fn local_addrs_by_filter<F>(f: F) -> io::Result<SmallVec<IfNet>>
where
  F: FnMut(&IpAddr) -> bool,
{
  os::local_addrs_by_filter(f)
}

/// Returns the IPv4 addresses from the interface(s) with the best default route.
/// The "best" interface is determined by the routing metrics of default routes (`0.0.0.0`).
///
/// Best-effort on Linux: only the built-in RPDB tables (`local`, `main`,
/// `default`) are consulted; hosts with unconstrained custom `ip rule`
/// policies ahead of `main` may have outbound traffic routed via a
/// custom table this call does not see.
///
/// Best-effort on FreeBSD / macOS / NetBSD / DragonFly: those kernels
/// don't expose a documented routing priority on `rt_msghdr` — only
/// OpenBSD does (`rtm_priority`). On the others, every default route
/// is treated as equal-best, so a host with multiple defaults (VPN +
/// physical link, primary + backup WAN) gets addresses from *all* of
/// them rather than the single one the kernel would actually pick;
/// callers needing kernel-equivalent selection should issue
/// `RTM_GET` over `PF_ROUTE` themselves.
///
/// See also [`local_ipv4_addrs`].
///
/// ## Example
///
/// ```rust
/// use getifs::best_local_ipv4_addrs;
///
/// let ipv4_addrs = best_local_ipv4_addrs().unwrap();
/// for addr in ipv4_addrs {
///   println!("{addr}");
/// }
/// ```
pub fn best_local_ipv4_addrs() -> io::Result<SmallVec<Ifv4Net>> {
  os::best_local_ipv4_addrs()
}

/// Returns the IPv6 addresses from the interface(s) with the best default route.
/// The "best" interface is determined by the routing metrics of default routes (`::`).
///
/// Best-effort on Linux: only the built-in RPDB tables (`local`, `main`,
/// `default`) are consulted; hosts with unconstrained custom `ip rule`
/// policies ahead of `main` may have outbound traffic routed via a
/// custom table this call does not see.
///
/// Best-effort on FreeBSD / macOS / NetBSD / DragonFly: those kernels
/// don't expose a documented routing priority on `rt_msghdr` — only
/// OpenBSD does (`rtm_priority`). On the others, every default route
/// is treated as equal-best, so a host with multiple defaults gets
/// addresses from *all* of them rather than the single one the
/// kernel would actually pick; callers needing kernel-equivalent
/// selection should issue `RTM_GET` over `PF_ROUTE` themselves.
///
/// See also [`local_ipv6_addrs`].
///
/// ## Example
///
/// ```rust
/// use getifs::best_local_ipv6_addrs;
///
/// let ipv6_addrs = best_local_ipv6_addrs().unwrap();
/// // Will only contain addresses from the interface with best default route
/// for addr in ipv6_addrs {
///   println!("{addr}");
/// }
/// ```
pub fn best_local_ipv6_addrs() -> io::Result<SmallVec<Ifv6Net>> {
  os::best_local_ipv6_addrs()
}

/// Returns both IPv4 and IPv6 addresses from the interfaces with the best default routes.
/// The "best" interfaces are determined by the routing metrics of default routes.
///
/// Best-effort on Linux: only the built-in RPDB tables (`local`, `main`,
/// `default`) are consulted; hosts with unconstrained custom `ip rule`
/// policies ahead of `main` may have outbound traffic routed via a
/// custom table this call does not see.
///
/// Best-effort on FreeBSD / macOS / NetBSD / DragonFly: those kernels
/// don't expose a documented routing priority on `rt_msghdr` — only
/// OpenBSD does (`rtm_priority`). On the others, every default route
/// is treated as equal-best, so a host with multiple defaults gets
/// addresses from *all* of them rather than the single one the
/// kernel would actually pick; callers needing kernel-equivalent
/// selection should issue `RTM_GET` over `PF_ROUTE` themselves.
///
/// See also [`local_addrs`].
///
/// ## Example
///
/// ```rust
/// use getifs::best_local_addrs;
///
/// let all_addrs = best_local_addrs().unwrap();
/// // Will only contain addresses from interfaces with best default routes
/// for addr in all_addrs {
///   println!("{addr}");
/// }
/// ```
pub fn best_local_addrs() -> io::Result<SmallVec<IfNet>> {
  os::best_local_addrs()
}