| //! Low-level Linux network device access |
| //! |
| //! The methods in this module take a socket's file descriptor to communicate with |
| //! the kernel in their ioctl call: |
| //! - glibc uses an `AF_UNIX`, `AF_INET`, or `AF_INET6` socket. |
| //! The address family itself does not matter and glibc tries the next address family if socket creation with one fails. |
| //! - Android (bionic) uses an `AF_INET` socket. |
| //! - Both create the socket with `SOCK_DGRAM|SOCK_CLOEXEC` type/flag. |
| //! - The [man-pages] specify, that the ioctl calls "can be used on any socket's file descriptor regardless of the |
| //! family or type". |
| //! |
| //! # References |
| //! - [Linux] |
| //! |
| //! [man-pages]: https://man7.org/linux/man-pages/man7/netdevice.7.html |
| //! [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html |
| |
| #[cfg(feature = "alloc")] |
| use crate::alloc::string::String; |
| use crate::fd::AsFd; |
| use crate::io; |
| |
| /// `ioctl(fd, SIOCGIFINDEX, ifreq)`—Returns the interface index for a given name. |
| /// |
| /// See the [module-level documentation] for information about `fd` usage. |
| /// |
| /// # References |
| /// - [Linux] |
| /// |
| /// [module-level documentation]: self |
| /// [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html |
| #[inline] |
| #[doc(alias = "SIOCGIFINDEX")] |
| pub fn name_to_index(fd: impl AsFd, if_name: &str) -> io::Result<u32> { |
| crate::backend::net::netdevice::name_to_index(fd, if_name) |
| } |
| |
| /// `ioctl(fd, SIOCGIFNAME, ifreq)`—Returns the interface name for a given index. |
| /// |
| /// See the [module-level documentation] for information about `fd` usage. |
| /// |
| /// # References |
| /// - [Linux] |
| /// |
| /// [module-level documentation]: self |
| /// [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html |
| #[inline] |
| #[doc(alias = "SIOCGIFNAME")] |
| #[cfg(feature = "alloc")] |
| pub fn index_to_name(fd: impl AsFd, index: u32) -> io::Result<String> { |
| crate::backend::net::netdevice::index_to_name(fd, index) |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use crate::backend::net::netdevice::{index_to_name, name_to_index}; |
| use crate::net::{AddressFamily, SocketFlags, SocketType}; |
| |
| #[test] |
| fn test_name_to_index() { |
| let fd = crate::net::socket_with( |
| AddressFamily::INET, |
| SocketType::DGRAM, |
| SocketFlags::CLOEXEC, |
| None, |
| ) |
| .unwrap(); |
| |
| let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex") |
| .unwrap() |
| .as_str() |
| .split_at(1) |
| .0 |
| .parse::<u32>() |
| .unwrap(); |
| assert_eq!(Ok(loopback_index), name_to_index(fd, "lo")); |
| } |
| |
| #[test] |
| #[cfg(feature = "alloc")] |
| fn test_index_to_name() { |
| let fd = crate::net::socket_with( |
| AddressFamily::INET, |
| SocketType::DGRAM, |
| SocketFlags::CLOEXEC, |
| None, |
| ) |
| .unwrap(); |
| |
| let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex") |
| .unwrap() |
| .as_str() |
| .split_at(1) |
| .0 |
| .parse::<u32>() |
| .unwrap(); |
| assert_eq!(Ok("lo".to_owned()), index_to_name(fd, loopback_index)); |
| } |
| } |