| 1 | //! Low-level Linux network device access |
| 2 | //! |
| 3 | //! The methods in this module take a socket's file descriptor to communicate |
| 4 | //! with the kernel in their ioctl call: |
| 5 | //! - glibc uses an `AF_UNIX`, `AF_INET`, or `AF_INET6` socket. The address |
| 6 | //! family itself does not matter and glibc tries the next address family if |
| 7 | //! socket creation with one fails. |
| 8 | //! - Android (bionic) uses an `AF_INET` socket. |
| 9 | //! - Both create the socket with `SOCK_DGRAM|SOCK_CLOEXEC` type/flag. |
| 10 | //! - The [manual pages] specify that the ioctl calls “can be used on any |
| 11 | //! socket's file descriptor regardless of the family or type”. |
| 12 | //! |
| 13 | //! # References |
| 14 | //! - [Linux] |
| 15 | //! |
| 16 | //! [manual pages]: https://man7.org/linux/man-pages/man7/netdevice.7.html |
| 17 | //! [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html |
| 18 | |
| 19 | use crate::fd::AsFd; |
| 20 | use crate::io; |
| 21 | #[cfg (feature = "alloc" )] |
| 22 | use alloc::string::String; |
| 23 | |
| 24 | /// `ioctl(fd, SIOCGIFINDEX, ifreq)`—Returns the interface index for a given |
| 25 | /// name. |
| 26 | /// |
| 27 | /// See the [module-level documentation] for information about `fd` usage. |
| 28 | /// |
| 29 | /// # References |
| 30 | /// - [Linux] |
| 31 | /// |
| 32 | /// [module-level documentation]: self |
| 33 | /// [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html |
| 34 | #[inline ] |
| 35 | #[doc (alias = "SIOCGIFINDEX" )] |
| 36 | pub fn name_to_index(fd: impl AsFd, if_name: &str) -> io::Result<u32> { |
| 37 | crate::backend::net::netdevice::name_to_index(fd, if_name) |
| 38 | } |
| 39 | |
| 40 | /// `ioctl(fd, SIOCGIFNAME, ifreq)`—Returns the interface name for a given |
| 41 | /// index. |
| 42 | /// |
| 43 | /// See the [module-level documentation] for information about `fd` usage. |
| 44 | /// |
| 45 | /// # References |
| 46 | /// - [Linux] |
| 47 | /// |
| 48 | /// [module-level documentation]: self |
| 49 | /// [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html |
| 50 | #[inline ] |
| 51 | #[doc (alias = "SIOCGIFNAME" )] |
| 52 | #[cfg (feature = "alloc" )] |
| 53 | pub fn index_to_name(fd: impl AsFd, index: u32) -> io::Result<String> { |
| 54 | crate::backend::net::netdevice::index_to_name(fd, index) |
| 55 | } |
| 56 | |
| 57 | #[cfg (test)] |
| 58 | mod tests { |
| 59 | use crate::backend::net::netdevice::{index_to_name, name_to_index}; |
| 60 | use crate::net::{AddressFamily, SocketFlags, SocketType}; |
| 61 | |
| 62 | #[test ] |
| 63 | fn test_name_to_index() { |
| 64 | let fd = crate::net::socket_with( |
| 65 | AddressFamily::INET, |
| 66 | SocketType::DGRAM, |
| 67 | SocketFlags::CLOEXEC, |
| 68 | None, |
| 69 | ) |
| 70 | .unwrap(); |
| 71 | |
| 72 | let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex" ) |
| 73 | .unwrap() |
| 74 | .as_str() |
| 75 | .split_at(1) |
| 76 | .0 |
| 77 | .parse::<u32>() |
| 78 | .unwrap(); |
| 79 | assert_eq!(Ok(loopback_index), name_to_index(fd, "lo" )); |
| 80 | } |
| 81 | |
| 82 | #[test ] |
| 83 | #[cfg (feature = "alloc" )] |
| 84 | fn test_index_to_name() { |
| 85 | let fd = crate::net::socket_with( |
| 86 | AddressFamily::INET, |
| 87 | SocketType::DGRAM, |
| 88 | SocketFlags::CLOEXEC, |
| 89 | None, |
| 90 | ) |
| 91 | .unwrap(); |
| 92 | |
| 93 | let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex" ) |
| 94 | .unwrap() |
| 95 | .as_str() |
| 96 | .split_at(1) |
| 97 | .0 |
| 98 | .parse::<u32>() |
| 99 | .unwrap(); |
| 100 | assert_eq!(Ok("lo" .to_owned()), index_to_name(fd, loopback_index)); |
| 101 | } |
| 102 | } |
| 103 | |