rustix/net/
netdevice.rs

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
19use crate::fd::AsFd;
20use crate::io;
21#[cfg(feature = "alloc")]
22use 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")]
36pub fn name_to_index<Fd: AsFd>(fd: Fd, if_name: &str) -> io::Result<u32> {
37    crate::backend::net::netdevice::name_to_index(fd.as_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#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
54pub fn index_to_name<Fd: AsFd>(fd: Fd, index: u32) -> io::Result<String> {
55    crate::backend::net::netdevice::index_to_name(fd.as_fd(), index)
56}
57
58#[cfg(test)]
59mod tests {
60    use crate::backend::net::netdevice::{index_to_name, name_to_index};
61    use crate::fd::AsFd;
62    use crate::net::{AddressFamily, SocketFlags, SocketType};
63
64    #[test]
65    fn test_name_to_index() {
66        let fd = crate::net::socket_with(
67            AddressFamily::INET,
68            SocketType::DGRAM,
69            SocketFlags::CLOEXEC,
70            None,
71        )
72        .unwrap();
73
74        let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex")
75            .unwrap()
76            .as_str()
77            .split_at(1)
78            .0
79            .parse::<u32>()
80            .unwrap();
81        assert_eq!(Ok(loopback_index), name_to_index(fd.as_fd(), "lo"));
82    }
83
84    #[test]
85    #[cfg(feature = "alloc")]
86    fn test_index_to_name() {
87        let fd = crate::net::socket_with(
88            AddressFamily::INET,
89            SocketType::DGRAM,
90            SocketFlags::CLOEXEC,
91            None,
92        )
93        .unwrap();
94
95        let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex")
96            .unwrap()
97            .as_str()
98            .split_at(1)
99            .0
100            .parse::<u32>()
101            .unwrap();
102        assert_eq!(
103            Ok("lo".to_owned()),
104            index_to_name(fd.as_fd(), loopback_index)
105        );
106    }
107}