Switch to rustix for netlink bind/recvfrom
This commit is contained in:
parent
53a3fe41fc
commit
0e145f89a6
2 changed files with 24 additions and 55 deletions
|
|
@ -23,7 +23,6 @@ futures-lite = "1.13.0"
|
|||
|
||||
[target.'cfg(any(target_os="linux", target_os="android"))'.dependencies]
|
||||
rustix = { version = "1.0.1", features = ["fs", "event", "net"] }
|
||||
libc = "0.2.155"
|
||||
|
||||
[target.'cfg(target_os="windows")'.dependencies]
|
||||
windows-sys = { version = "0.59.0", features = ["Win32_Devices_Usb", "Win32_Devices_DeviceAndDriverInstallation", "Win32_Foundation", "Win32_Devices_Properties", "Win32_Storage_FileSystem", "Win32_Security", "Win32_System_IO", "Win32_System_Registry", "Win32_System_Com"] }
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
use libc::{sockaddr, sockaddr_nl, socklen_t, AF_NETLINK, MSG_DONTWAIT};
|
||||
use log::{error, trace, warn};
|
||||
use rustix::{
|
||||
fd::{AsFd, AsRawFd, OwnedFd},
|
||||
net::{netlink, socket_with, AddressFamily, SocketFlags, SocketType},
|
||||
};
|
||||
use std::{
|
||||
io::ErrorKind,
|
||||
mem,
|
||||
os::{raw::c_void, unix::prelude::BorrowedFd},
|
||||
path::Path,
|
||||
task::Poll,
|
||||
fd::{AsFd, OwnedFd},
|
||||
io::Errno,
|
||||
net::{
|
||||
bind,
|
||||
netlink::{self, SocketAddrNetlink},
|
||||
recvfrom, socket_with, AddressFamily, RecvFlags, SocketFlags, SocketType,
|
||||
},
|
||||
};
|
||||
use std::{mem::MaybeUninit, os::unix::prelude::BorrowedFd, path::Path, task::Poll};
|
||||
|
||||
use crate::{hotplug::HotplugEvent, Error};
|
||||
|
||||
|
|
@ -31,23 +29,7 @@ impl LinuxHotplugWatch {
|
|||
SocketFlags::CLOEXEC,
|
||||
Some(netlink::KOBJECT_UEVENT),
|
||||
)?;
|
||||
|
||||
unsafe {
|
||||
// rustix doesn't support netlink yet (pending https://github.com/bytecodealliance/rustix/pull/1004)
|
||||
// so use libc for now.
|
||||
let mut addr: sockaddr_nl = mem::zeroed();
|
||||
addr.nl_family = AF_NETLINK as u16;
|
||||
addr.nl_groups = UDEV_MULTICAST_GROUP;
|
||||
let r = libc::bind(
|
||||
fd.as_raw_fd(),
|
||||
&addr as *const sockaddr_nl as *const sockaddr,
|
||||
mem::size_of_val(&addr) as socklen_t,
|
||||
);
|
||||
if r != 0 {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
}
|
||||
|
||||
bind(&fd, &SocketAddrNetlink::new(0, UDEV_MULTICAST_GROUP))?;
|
||||
Ok(LinuxHotplugWatch {
|
||||
fd: Async::new(fd)?,
|
||||
})
|
||||
|
|
@ -67,40 +49,28 @@ impl LinuxHotplugWatch {
|
|||
}
|
||||
|
||||
fn try_receive_event(fd: BorrowedFd) -> Option<HotplugEvent> {
|
||||
let mut buf = [0; 8192];
|
||||
let mut buf = [MaybeUninit::uninit(); 8192];
|
||||
|
||||
let received = unsafe {
|
||||
let mut addr: sockaddr_nl = mem::zeroed();
|
||||
let mut addrlen: socklen_t = mem::size_of_val(&addr) as socklen_t;
|
||||
let r = libc::recvfrom(
|
||||
fd.as_raw_fd(),
|
||||
buf.as_mut_ptr() as *mut c_void,
|
||||
buf.len(),
|
||||
MSG_DONTWAIT,
|
||||
&mut addr as *mut sockaddr_nl as *mut sockaddr,
|
||||
&mut addrlen,
|
||||
);
|
||||
if r >= 0 {
|
||||
Ok((r as usize, addr.nl_groups))
|
||||
} else {
|
||||
Err(Error::last_os_error())
|
||||
let (data, src) = match recvfrom(fd, &mut buf, RecvFlags::DONTWAIT) {
|
||||
Ok(((buf, _), _, src)) => (buf, src),
|
||||
Err(Errno::AGAIN | Errno::INTR) => return None,
|
||||
Err(e) => {
|
||||
error!("udev netlink socket recvfrom failed with {e}");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
match received {
|
||||
// udev messages will normally be sent to a multicast group, which only
|
||||
// root can send to. Reject unicast messages that may be from anywhere.
|
||||
Ok((size, groups)) if groups == UDEV_MULTICAST_GROUP => parse_packet(&buf[..size]),
|
||||
Ok((_, src)) => {
|
||||
// udev messages will normally be sent to a multicast group, which only
|
||||
// root can send to. Reject unicast messages that may be from anywhere.
|
||||
match src.map(SocketAddrNetlink::try_from).transpose() {
|
||||
Ok(Some(nl)) if nl.groups() == UDEV_MULTICAST_GROUP => {}
|
||||
src => {
|
||||
warn!("udev netlink socket received message from {src:?}");
|
||||
None
|
||||
}
|
||||
Err(e) if e.kind() == ErrorKind::WouldBlock => None,
|
||||
Err(e) => {
|
||||
error!("udev netlink socket recvfrom failed with {e}");
|
||||
None
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
parse_packet(data)
|
||||
}
|
||||
|
||||
fn parse_packet(buf: &[u8]) -> Option<HotplugEvent> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue