//! Network interface name resolution. //! //! Uses Linux and/or POSIX functions to resolve interface names like "eth0" //! or "socan1" into device numbers.
use std::{ffi::{CStr, CString}, fmt}; usecrate::{errno::Errno, Error, NixPath, Result}; use libc::{c_uint, IF_NAMESIZE};
#[cfg(not(solarish))] /// type alias for InterfaceFlags pubtype IflagsType = libc::c_int; #[cfg(solarish)] /// type alias for InterfaceFlags pubtype IflagsType = libc::c_longlong;
/// Resolve an interface into an interface number. pubfn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> { let if_index = name
.with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?;
/// Resolve an interface number into an interface. pubfn if_indextoname(index: c_uint) -> Result<CString> { // We need to allocate this anyway, so doing it directly is faster. letmut buf = vec![0u8; IF_NAMESIZE];
let return_buf = unsafe {
libc::if_indextoname(index, buf.as_mut_ptr().cast())
};
libc_bitflags!( /// Standard interface flags, used by `getifaddrs` pubstruct InterfaceFlags: IflagsType {
/// Interface is running. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
IFF_UP as IflagsType; /// Valid broadcast address set. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
IFF_BROADCAST as IflagsType; /// Internal debugging flag. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) #[cfg(not(any(target_os = "haiku", target_os = "cygwin")))]
IFF_DEBUG as IflagsType; /// Interface is a loopback interface. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
IFF_LOOPBACK as IflagsType; /// Interface is a point-to-point link. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
IFF_POINTOPOINT as IflagsType; /// Avoid use of trailers. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) #[cfg(any(
linux_android,
solarish,
apple_targets,
target_os = "fuchsia",
target_os = "netbsd",
target_os = "cygwin"))]
IFF_NOTRAILERS as IflagsType; /// Interface manages own routes. #[cfg(any(target_os = "dragonfly"))]
IFF_SMART as IflagsType; /// Resources allocated. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) #[cfg(any(
linux_android,
bsd,
solarish,
target_os = "fuchsia",
target_os = "cygwin"))]
IFF_RUNNING as IflagsType; /// No arp protocol, L2 destination address not set. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
IFF_NOARP as IflagsType; /// Interface is in promiscuous mode. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
IFF_PROMISC as IflagsType; /// Receive all multicast packets. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) #[cfg(not(target_os = "cygwin"))]
IFF_ALLMULTI as IflagsType; /// Master of a load balancing bundle. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_MASTER; /// transmission in progress, tx hardware queue is full #[cfg(any(target_os = "freebsd", apple_targets, netbsdlike))]
IFF_OACTIVE; /// Protocol code on board. #[cfg(solarish)]
IFF_INTELLIGENT as IflagsType; /// Slave of a load balancing bundle. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_SLAVE; /// Can't hear own transmissions. #[cfg(bsd)]
IFF_SIMPLEX; /// Supports multicast. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
IFF_MULTICAST as IflagsType; /// Per link layer defined bit. #[cfg(bsd)]
IFF_LINK0; /// Multicast using broadcast. #[cfg(solarish)]
IFF_MULTI_BCAST as IflagsType; /// Is able to select media type via ifmap. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_PORTSEL; /// Per link layer defined bit. #[cfg(bsd)]
IFF_LINK1; /// Non-unique address. #[cfg(solarish)]
IFF_UNNUMBERED as IflagsType; /// Auto media selection active. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_AUTOMEDIA; /// Per link layer defined bit. #[cfg(bsd)]
IFF_LINK2; /// Use alternate physical connection. #[cfg(any(freebsdlike, apple_targets))]
IFF_ALTPHYS; /// DHCP controls interface. #[cfg(solarish)]
IFF_DHCPRUNNING as IflagsType; /// The addresses are lost when the interface goes down. (see /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_DYNAMIC; /// Do not advertise. #[cfg(solarish)]
IFF_PRIVATE as IflagsType; /// Driver signals L1 up. Volatile. #[cfg(any(target_os = "fuchsia", target_os = "linux", target_os = "cygwin"))]
IFF_LOWER_UP; /// Interface is in polling mode. #[cfg(any(target_os = "dragonfly"))]
IFF_POLLING_COMPAT; /// Unconfigurable using ioctl(2). #[cfg(any(target_os = "freebsd"))]
IFF_CANTCONFIG; /// Do not transmit packets. #[cfg(solarish)]
IFF_NOXMIT as IflagsType; /// Driver signals dormant. Volatile. #[cfg(any(target_os = "fuchsia", target_os = "linux", target_os = "cygwin"))]
IFF_DORMANT; /// User-requested promisc mode. #[cfg(freebsdlike)]
IFF_PPROMISC; /// Just on-link subnet. #[cfg(solarish)]
IFF_NOLOCAL as IflagsType; /// Echo sent packets. Volatile. #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
IFF_ECHO; /// User-requested monitor mode. #[cfg(freebsdlike)]
IFF_MONITOR; /// Address is deprecated. #[cfg(solarish)]
IFF_DEPRECATED as IflagsType; /// Static ARP. #[cfg(freebsdlike)]
IFF_STATICARP; /// Address from stateless addrconf. #[cfg(solarish)]
IFF_ADDRCONF as IflagsType; /// Interface is in polling mode. #[cfg(any(target_os = "dragonfly"))]
IFF_NPOLLING; /// Router on interface. #[cfg(solarish)]
IFF_ROUTER as IflagsType; /// Interface is in polling mode. #[cfg(any(target_os = "dragonfly"))]
IFF_IDIRECT; /// Interface is winding down #[cfg(any(target_os = "freebsd"))]
IFF_DYING; /// No NUD on interface. #[cfg(solarish)]
IFF_NONUD as IflagsType; /// Interface is being renamed #[cfg(any(target_os = "freebsd"))]
IFF_RENAMING; /// Anycast address. #[cfg(solarish)]
IFF_ANYCAST as IflagsType; /// Don't exchange routing info. #[cfg(solarish)]
IFF_NORTEXCH as IflagsType; /// Do not provide packet information #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_NO_PI as IflagsType; /// TUN device (no Ethernet headers) #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_TUN as IflagsType; /// TAP device #[cfg(any(linux_android, target_os = "fuchsia"))]
IFF_TAP as IflagsType; /// IPv4 interface. #[cfg(solarish)]
IFF_IPV4 as IflagsType; /// IPv6 interface. #[cfg(solarish)]
IFF_IPV6 as IflagsType; /// in.mpathd test address #[cfg(solarish)]
IFF_NOFAILOVER as IflagsType; /// Interface has failed #[cfg(solarish)]
IFF_FAILED as IflagsType; /// Interface is a hot-spare #[cfg(solarish)]
IFF_STANDBY as IflagsType; /// Functioning but not used #[cfg(solarish)]
IFF_INACTIVE as IflagsType; /// Interface is offline #[cfg(solarish)]
IFF_OFFLINE as IflagsType; /// Has CoS marking supported #[cfg(solarish)]
IFF_COS_ENABLED as IflagsType; /// Prefer as source addr #[cfg(solarish)]
IFF_PREFERRED as IflagsType; /// RFC3041 #[cfg(solarish)]
IFF_TEMPORARY as IflagsType; /// MTU set #[cfg(solarish)]
IFF_FIXEDMTU as IflagsType; /// Cannot send/receive packets #[cfg(solarish)]
IFF_VIRTUAL as IflagsType; /// Local address in use #[cfg(solarish)]
IFF_DUPLICATE as IflagsType; /// IPMP IP interface #[cfg(solarish)]
IFF_IPMP as IflagsType;
}
);
use std::ffi::CStr; use std::fmt; use std::marker::PhantomData; use std::ptr::NonNull;
/// A network interface. Has a name like "eth0" or "wlp4s0" or "wlan0", as well as an index /// (1, 2, 3, etc) that identifies it in the OS's networking stack. #[allow(missing_copy_implementations)] #[repr(transparent)] pubstruct Interface(libc::if_nameindex);
impl Interface { /// Obtain the index of this interface. pubfn index(&self) -> c_uint { self.0.if_index
}
/// Obtain the name of this interface. pubfn name(&self) -> &CStr { unsafe { CStr::from_ptr(self.0.if_name) }
}
}
/// A list of the network interfaces available on this system. Obtained from [`if_nameindex()`]. #[repr(transparent)] pubstruct Interfaces {
ptr: NonNull<libc::if_nameindex>,
}
impl Interfaces { /// Iterate over the interfaces in this list. #[inline] pubfn iter(&self) -> InterfacesIter<'_> { self.into_iter()
}
/// Convert this to a slice of interfaces. Note that the underlying interfaces list is /// null-terminated, so calling this calculates the length. If random access isn't needed, /// [`Interfaces::iter()`] should be used instead. pubfn to_slice(&self) -> &[Interface] { let ifs = self.ptr.as_ptr().cast(); let len = self.iter().count(); unsafe { std::slice::from_raw_parts(ifs, len) }
}
}
impl Drop for Interfaces { fn drop(&mutself) { unsafe { libc::if_freenameindex(self.ptr.as_ptr()) };
}
}
impl<'a> IntoIterator for &'a Interfaces { type IntoIter = InterfacesIter<'a>; type Item = &'a Interface; #[inline] fn into_iter(self) -> Self::IntoIter {
InterfacesIter {
ptr: self.ptr.as_ptr(),
_marker: PhantomData,
}
}
}
/// An iterator over the interfaces in an [`Interfaces`]. #[derive(Debug)] pubstruct InterfacesIter<'a> {
ptr: *const libc::if_nameindex,
_marker: PhantomData<&'a Interfaces>,
}
impl<'a> Iterator for InterfacesIter<'a> { type Item = &'a Interface; #[inline] fn next(&mutself) -> Option<Self::Item> { unsafe { if (*self.ptr).if_index == 0 {
None
} else { let ret = &*(self.ptr as *const Interface); self.ptr = self.ptr.add(1);
Some(ret)
}
}
}
}
/// Retrieve a list of the network interfaces available on the local system. /// /// ``` /// let interfaces = nix::net::if_::if_nameindex().unwrap(); /// for iface in &interfaces { /// println!("Interface #{} is called {}", iface.index(), iface.name().to_string_lossy()); /// } /// ``` pubfn if_nameindex() -> Result<Interfaces> { unsafe { let ifs = libc::if_nameindex(); let ptr = NonNull::new(ifs).ok_or_else(Error::last)?;
Ok(Interfaces { ptr })
}
}
} #[cfg(any(
bsd,
target_os = "fuchsia",
target_os = "linux",
solarish,
))] pubuse if_nameindex::*;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.