| 1 | //! Wrappers for netdevice ioctls. |
| 2 | |
| 3 | #![allow (unsafe_code)] |
| 4 | |
| 5 | use crate::backend::io::syscalls::ioctl; |
| 6 | use crate::fd::AsFd; |
| 7 | use crate::io; |
| 8 | use core::ptr::addr_of_mut; |
| 9 | use core::{slice, str}; |
| 10 | use linux_raw_sys::ctypes::c_char; |
| 11 | use linux_raw_sys::ioctl::SIOCGIFINDEX; |
| 12 | #[cfg (feature = "alloc" )] |
| 13 | use linux_raw_sys::ioctl::SIOCGIFNAME; |
| 14 | use linux_raw_sys::net::{ifreq, ifreq__bindgen_ty_1, ifreq__bindgen_ty_2, IFNAMSIZ}; |
| 15 | #[cfg (feature = "alloc" )] |
| 16 | use {alloc::borrow::ToOwned, alloc::string::String}; |
| 17 | |
| 18 | pub(crate) fn name_to_index(fd: impl AsFd, if_name: &str) -> io::Result<u32> { |
| 19 | let if_name_bytes: &[u8] = if_name.as_bytes(); |
| 20 | if if_name_bytes.len() >= IFNAMSIZ as usize { |
| 21 | return Err(io::Errno::NODEV); |
| 22 | } |
| 23 | if if_name_bytes.contains(&0) { |
| 24 | return Err(io::Errno::NODEV); |
| 25 | } |
| 26 | |
| 27 | // SAFETY: Convert `&[u8]` to `&[c_char]`. |
| 28 | let if_name_bytes: &[u8] = unsafe { |
| 29 | slice::from_raw_parts(data:if_name_bytes.as_ptr().cast::<c_char>(), if_name_bytes.len()) |
| 30 | }; |
| 31 | |
| 32 | let mut ifreq: ifreq = ifreq { |
| 33 | ifr_ifrn: ifreq__bindgen_ty_1 { ifrn_name: [0; 16] }, |
| 34 | ifr_ifru: ifreq__bindgen_ty_2 { ifru_ivalue: 0 }, |
| 35 | }; |
| 36 | unsafe { ifreq.ifr_ifrn.ifrn_name[..if_name_bytes.len()].copy_from_slice(src:if_name_bytes) }; |
| 37 | |
| 38 | unsafe { ioctl(fd.as_fd(), SIOCGIFINDEX, arg:addr_of_mut!(ifreq).cast()) }?; |
| 39 | let index: i32 = unsafe { ifreq.ifr_ifru.ifru_ivalue }; |
| 40 | Ok(index as u32) |
| 41 | } |
| 42 | |
| 43 | #[cfg (feature = "alloc" )] |
| 44 | pub(crate) fn index_to_name(fd: impl AsFd, index: u32) -> io::Result<String> { |
| 45 | let mut ifreq = ifreq { |
| 46 | ifr_ifrn: ifreq__bindgen_ty_1 { ifrn_name: [0; 16] }, |
| 47 | ifr_ifru: ifreq__bindgen_ty_2 { |
| 48 | ifru_ivalue: index as _, |
| 49 | }, |
| 50 | }; |
| 51 | |
| 52 | unsafe { ioctl(fd.as_fd(), SIOCGIFNAME, addr_of_mut!(ifreq).cast()) }?; |
| 53 | |
| 54 | if let Some(nul_byte) = unsafe { ifreq.ifr_ifrn.ifrn_name } |
| 55 | .iter() |
| 56 | .position(|ch| *ch == 0) |
| 57 | { |
| 58 | let ifrn_name = unsafe { &ifreq.ifr_ifrn.ifrn_name[..nul_byte] }; |
| 59 | |
| 60 | // SAFETY: Convert `&[c_char]` to `&[u8]`. |
| 61 | let ifrn_name = |
| 62 | unsafe { slice::from_raw_parts(ifrn_name.as_ptr().cast::<u8>(), ifrn_name.len()) }; |
| 63 | |
| 64 | str::from_utf8(ifrn_name) |
| 65 | .map_err(|_| io::Errno::ILSEQ) |
| 66 | .map(ToOwned::to_owned) |
| 67 | } else { |
| 68 | Err(io::Errno::INVAL) |
| 69 | } |
| 70 | } |
| 71 | |