1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
use std::ffi::{OsString, OsStr, CString}; use std::os::unix::ffi::{OsStrExt, OsStringExt}; use std::os::unix::io::AsRawFd; use std::os::unix::net::UnixDatagram; use std::fs::File; use std::io::Read; use std::mem::MaybeUninit; use libc::ioctl; mod ffi; mod error; #[derive(Debug)] pub struct Interface { name: OsString, } impl Interface { pub fn find_interface<S: AsRef<str>>(name: S) -> Result<Option<Interface>, error::InterfaceListError> { let ifs = interfaces()?; Ok(ifs.into_iter().find(|i| i.name == name.as_ref())) } pub fn get_connected_essid(&self) -> Result<CString, error::EssidFetchError> { let socket = UnixDatagram::unbound()?; let socketfd = socket.as_raw_fd(); let mut wreq: ffi::iwreq = unsafe { MaybeUninit::zeroed().assume_init() }; let mut name = [0u8; 16]; name[0..self.name.len()].copy_from_slice(self.name.as_bytes()); unsafe { wreq.ifr_ifrn.ifrn_name.copy_from_slice(std::mem::transmute(&name[..])) }; wreq.u.essid.length = (ffi::IW_ESSID_MAX_SIZE + 1) as u16; let mut name: MaybeUninit<[u8; ffi::IW_ESSID_MAX_SIZE as usize + 1]> = MaybeUninit::uninit(); wreq.u.essid.pointer = name.as_mut_ptr() as *mut _; let ret = unsafe { ioctl(socketfd, ffi::SIOCGIWESSID.into(), &mut wreq as *mut _) }; if ret == -1 { return Err(std::io::Error::last_os_error())?; } Ok(CString::new(unsafe {&name.assume_init()[..wreq.u.essid.length as usize - 1]})?) } pub fn get_name(&self) -> &OsStr { &self.name } } pub fn interfaces() -> Result<Vec<Interface>, error::InterfaceListError> { let mut proc_wireless = File::open("/proc/net/wireless")?; let mut buf = vec![]; proc_wireless.read_to_end(&mut buf)?; Ok(buf.split(|&b| b == b'\n').skip(2) .flat_map(|line| line.split(|&c| c == b':').next()) .flat_map(|line| line.rsplit(|c| c.is_ascii_whitespace()).next()) .filter(|line| line.len() != 0) .map(|n| OsStr::from_bytes(n)) .map(|n| Interface { name: n.to_os_string() }) .collect()) }