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