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