-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add `name_to_index()` & `index_to_name()` * Update to libc 0.2.152.
- Loading branch information
1 parent
9095854
commit e460984
Showing
7 changed files
with
214 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#![allow(unsafe_code)] | ||
|
||
#[cfg(feature = "alloc")] | ||
use crate::alloc::string::String; | ||
use crate::backend::io::syscalls::ioctl; | ||
use crate::fd::AsFd; | ||
use crate::io; | ||
#[cfg(feature = "alloc")] | ||
use libc::SIOCGIFNAME; | ||
use libc::{__c_anonymous_ifr_ifru, c_char, ifreq, IFNAMSIZ, SIOCGIFINDEX}; | ||
|
||
pub(crate) fn name_to_index(fd: impl AsFd, if_name: &str) -> io::Result<u32> { | ||
let if_name_bytes = if_name.as_bytes(); | ||
if if_name_bytes.len() >= IFNAMSIZ as usize { | ||
return Err(io::Errno::NODEV); | ||
} | ||
|
||
let mut ifreq = ifreq { | ||
ifr_name: [0; 16], | ||
ifr_ifru: __c_anonymous_ifr_ifru { ifru_ifindex: 0 }, | ||
}; | ||
|
||
let mut if_name_c_char_iter = if_name_bytes.iter().map(|byte| *byte as c_char); | ||
ifreq.ifr_name[..if_name_bytes.len()].fill_with(|| if_name_c_char_iter.next().unwrap()); | ||
|
||
unsafe { ioctl(fd.as_fd(), SIOCGIFINDEX as _, &mut ifreq as *mut ifreq as _) }?; | ||
let index = unsafe { ifreq.ifr_ifru.ifru_ifindex }; | ||
Ok(index as u32) | ||
} | ||
|
||
#[cfg(feature = "alloc")] | ||
pub(crate) fn index_to_name(fd: impl AsFd, index: u32) -> io::Result<String> { | ||
let mut ifreq = ifreq { | ||
ifr_name: [0; 16], | ||
ifr_ifru: __c_anonymous_ifr_ifru { | ||
ifru_ifindex: index as _, | ||
}, | ||
}; | ||
|
||
unsafe { ioctl(fd.as_fd(), SIOCGIFNAME as _, &mut ifreq as *mut ifreq as _) }?; | ||
|
||
if let Some(nul_byte) = ifreq.ifr_name.iter().position(|char| *char == 0) { | ||
let name: String = ifreq.ifr_name[..nul_byte] | ||
.iter() | ||
.map(|v| *v as u8 as char) | ||
.collect(); | ||
|
||
Ok(name) | ||
} else { | ||
Err(io::Errno::INVAL) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#![allow(unsafe_code)] | ||
|
||
#[cfg(feature = "alloc")] | ||
use crate::alloc::string::String; | ||
use crate::backend::io::syscalls::ioctl; | ||
use crate::fd::AsFd; | ||
use crate::io; | ||
use linux_raw_sys::ioctl::SIOCGIFINDEX; | ||
#[cfg(feature = "alloc")] | ||
use linux_raw_sys::ioctl::SIOCGIFNAME; | ||
use linux_raw_sys::net::{ifreq, ifreq__bindgen_ty_1, ifreq__bindgen_ty_2, IFNAMSIZ}; | ||
|
||
pub(crate) fn name_to_index(fd: impl AsFd, if_name: &str) -> io::Result<u32> { | ||
let if_name_bytes = if_name.as_bytes(); | ||
if if_name_bytes.len() >= IFNAMSIZ as usize { | ||
return Err(io::Errno::NODEV); | ||
} | ||
|
||
let mut ifreq = ifreq { | ||
ifr_ifrn: ifreq__bindgen_ty_1 { ifrn_name: [0; 16] }, | ||
ifr_ifru: ifreq__bindgen_ty_2 { ifru_ivalue: 0 }, | ||
}; | ||
unsafe { ifreq.ifr_ifrn.ifrn_name[..if_name_bytes.len()].copy_from_slice(if_name_bytes) }; | ||
|
||
unsafe { ioctl(fd.as_fd(), SIOCGIFINDEX, &mut ifreq as *mut ifreq as _) }?; | ||
let index = unsafe { ifreq.ifr_ifru.ifru_ivalue }; | ||
Ok(index as u32) | ||
} | ||
|
||
#[cfg(feature = "alloc")] | ||
pub(crate) fn index_to_name(fd: impl AsFd, index: u32) -> io::Result<String> { | ||
let mut ifreq = ifreq { | ||
ifr_ifrn: ifreq__bindgen_ty_1 { ifrn_name: [0; 16] }, | ||
ifr_ifru: ifreq__bindgen_ty_2 { | ||
ifru_ivalue: index as _, | ||
}, | ||
}; | ||
|
||
unsafe { ioctl(fd.as_fd(), SIOCGIFNAME, &mut ifreq as *mut ifreq as _) }?; | ||
|
||
if let Some(nul_byte) = unsafe { ifreq.ifr_ifrn.ifrn_name } | ||
.iter() | ||
.position(|char| *char == 0) | ||
{ | ||
let name = unsafe { ifreq.ifr_ifrn.ifrn_name }[..nul_byte] | ||
.iter() | ||
.map(|v| *v as char) | ||
.collect(); | ||
|
||
Ok(name) | ||
} else { | ||
Err(io::Errno::INVAL) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
//! Low-level Linux network device access | ||
//! | ||
//! The methods in this module take a socket's file descriptor to communicate with | ||
//! the kernel in their ioctl call: | ||
//! - glibc uses an `AF_UNIX`, `AF_INET`, or `AF_INET6` socket. | ||
//! The address family itself does not matter and glibc tries the next address family if socket creation with one fails. | ||
//! - Android (bionic) uses an `AF_INET` socket. | ||
//! - Both create the socket with `SOCK_DGRAM|SOCK_CLOEXEC` type/flag. | ||
//! - The [man-pages] specify, that the ioctl calls "can be used on any socket's file descriptor regardless of the | ||
//! family or type". | ||
//! | ||
//! # References | ||
//! - [Linux] | ||
//! | ||
//! [man-pages]: https://man7.org/linux/man-pages/man7/netdevice.7.html | ||
//! [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html | ||
|
||
#[cfg(feature = "alloc")] | ||
use crate::alloc::string::String; | ||
use crate::fd::AsFd; | ||
use crate::io; | ||
|
||
/// `ioctl(fd, SIOCGIFINDEX, ifreq)`—Returns the interface index for a given name. | ||
/// | ||
/// See the [module-level documentation] for information about `fd` usage. | ||
/// | ||
/// # References | ||
/// - [Linux] | ||
/// | ||
/// [module-level documentation]: self | ||
/// [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html | ||
#[inline] | ||
#[doc(alias = "SIOCGIFINDEX")] | ||
pub fn name_to_index(fd: impl AsFd, if_name: &str) -> io::Result<u32> { | ||
crate::backend::net::netdevice::name_to_index(fd, if_name) | ||
} | ||
|
||
/// `ioctl(fd, SIOCGIFNAME, ifreq)`—Returns the interface name for a given index. | ||
/// | ||
/// See the [module-level documentation] for information about `fd` usage. | ||
/// | ||
/// # References | ||
/// - [Linux] | ||
/// | ||
/// [module-level documentation]: self | ||
/// [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html | ||
#[inline] | ||
#[doc(alias = "SIOCGIFNAME")] | ||
#[cfg(feature = "alloc")] | ||
pub fn index_to_name(fd: impl AsFd, index: u32) -> io::Result<String> { | ||
crate::backend::net::netdevice::index_to_name(fd, index) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::backend::net::netdevice::{index_to_name, name_to_index}; | ||
use crate::net::{AddressFamily, SocketFlags, SocketType}; | ||
|
||
#[test] | ||
fn test_name_to_index() { | ||
let fd = crate::net::socket_with( | ||
AddressFamily::INET, | ||
SocketType::DGRAM, | ||
SocketFlags::CLOEXEC, | ||
None, | ||
) | ||
.unwrap(); | ||
|
||
let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex") | ||
.unwrap() | ||
.as_str() | ||
.split_at(1) | ||
.0 | ||
.parse::<u32>() | ||
.unwrap(); | ||
assert_eq!(Ok(loopback_index), name_to_index(fd, "lo")); | ||
} | ||
|
||
#[test] | ||
#[cfg(feature = "alloc")] | ||
fn test_index_to_name() { | ||
let fd = crate::net::socket_with( | ||
AddressFamily::INET, | ||
SocketType::DGRAM, | ||
SocketFlags::CLOEXEC, | ||
None, | ||
) | ||
.unwrap(); | ||
|
||
let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex") | ||
.unwrap() | ||
.as_str() | ||
.split_at(1) | ||
.0 | ||
.parse::<u32>() | ||
.unwrap(); | ||
assert_eq!(Ok("lo".to_owned()), index_to_name(fd, loopback_index)); | ||
} | ||
} |