|
1 | 1 | //! Low-level Linux network device access
|
2 | 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 | +//! |
3 | 12 | //! # References
|
4 | 13 | //! - [Linux]
|
5 | 14 | //!
|
| 15 | +//! [man-pages]: https://man7.org/linux/man-pages/man7/netdevice.7.html |
6 | 16 | //! [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html
|
7 | 17 |
|
8 | 18 | #[cfg(feature = "alloc")]
|
9 | 19 | use crate::alloc::string::String;
|
10 |
| -use crate::fd::OwnedFd; |
| 20 | +use crate::fd::AsFd; |
11 | 21 | use crate::io;
|
12 |
| -use crate::io::Errno; |
13 |
| -use crate::net::{socket, AddressFamily, SocketType}; |
14 |
| - |
15 |
| -/// Creates a socket used to communicate with the kernel in the ioctl calls. |
16 |
| -#[cfg(target_os = "linux")] |
17 |
| -pub(crate) fn open_socket() -> io::Result<OwnedFd> { |
18 |
| - if let Ok(fd) = socket(AddressFamily::UNIX, SocketType::DGRAM, None) { |
19 |
| - Ok(fd) |
20 |
| - } else if let Ok(fd) = socket(AddressFamily::INET, SocketType::DGRAM, None) { |
21 |
| - Ok(fd) |
22 |
| - } else if let Ok(fd) = socket(AddressFamily::INET6, SocketType::DGRAM, None) { |
23 |
| - Ok(fd) |
24 |
| - } else { |
25 |
| - Err(Errno::NOENT) |
26 |
| - } |
27 |
| -} |
28 | 22 |
|
29 | 23 | /// `ioctl(fd, SIOCGIFINDEX, ifreq)`—Returns the interface index for a given name.
|
30 | 24 | ///
|
| 25 | +/// See the [module-level documentation] for information about `fd` usage. |
| 26 | +/// |
31 | 27 | /// # References
|
32 | 28 | /// - [Linux]
|
33 | 29 | ///
|
| 30 | +/// [module-level documentation]: self |
34 | 31 | /// [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html
|
35 | 32 | #[inline]
|
36 | 33 | #[doc(alias = "SIOCGIFINDEX")]
|
37 |
| -#[cfg(target_os = "linux")] |
38 |
| -pub fn name_to_index(if_name: &str) -> io::Result<u32> { |
39 |
| - crate::backend::net::netdevice::name_to_index(if_name) |
| 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) |
40 | 36 | }
|
41 | 37 |
|
42 | 38 | /// `ioctl(fd, SIOCGIFNAME, ifreq)`—Returns the interface name for a given index.
|
43 | 39 | ///
|
| 40 | +/// See the [module-level documentation] for information about `fd` usage. |
| 41 | +/// |
44 | 42 | /// # References
|
45 | 43 | /// - [Linux]
|
46 | 44 | ///
|
| 45 | +/// [module-level documentation]: self |
47 | 46 | /// [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html
|
48 | 47 | #[inline]
|
49 | 48 | #[doc(alias = "SIOCGIFNAME")]
|
50 |
| -#[cfg(all(target_os = "linux", feature = "alloc"))] |
51 |
| -pub fn index_to_name(index: u32) -> io::Result<String> { |
52 |
| - crate::backend::net::netdevice::index_to_name(index) |
| 49 | +#[cfg(feature = "alloc")] |
| 50 | +pub fn index_to_name(fd: impl AsFd, index: u32) -> io::Result<String> { |
| 51 | + crate::backend::net::netdevice::index_to_name(fd, index) |
53 | 52 | }
|
54 | 53 |
|
55 | 54 | #[cfg(test)]
|
56 | 55 | mod tests {
|
57 | 56 | use crate::backend::net::netdevice::{index_to_name, name_to_index};
|
| 57 | + use crate::net::{AddressFamily, SocketFlags, SocketType}; |
58 | 58 |
|
59 | 59 | #[test]
|
60 |
| - #[cfg(target_os = "linux")] |
61 | 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 | + |
62 | 69 | let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex")
|
63 | 70 | .unwrap()
|
64 | 71 | .as_str()
|
65 | 72 | .split_at(1)
|
66 | 73 | .0
|
67 | 74 | .parse::<u32>()
|
68 | 75 | .unwrap();
|
69 |
| - assert_eq!(Ok(loopback_index), name_to_index("lo")); |
| 76 | + assert_eq!(Ok(loopback_index), name_to_index(fd, "lo")); |
70 | 77 | }
|
71 | 78 |
|
72 | 79 | #[test]
|
73 |
| - #[cfg(all(target_os = "linux", feature = "alloc"))] |
| 80 | + #[cfg(feature = "alloc")] |
74 | 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 | + |
75 | 90 | let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex")
|
76 | 91 | .unwrap()
|
77 | 92 | .as_str()
|
78 | 93 | .split_at(1)
|
79 | 94 | .0
|
80 | 95 | .parse::<u32>()
|
81 | 96 | .unwrap();
|
82 |
| - assert_eq!(Ok("lo".to_owned()), index_to_name(loopback_index)); |
| 97 | + assert_eq!(Ok("lo".to_owned()), index_to_name(fd, loopback_index)); |
83 | 98 | }
|
84 | 99 | }
|
0 commit comments