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
73
74
75
76
77
78
79
80
81
use std::os::unix::net::UnixStream;
use std::{
mem,
net::{SocketAddrV4, SocketAddrV6},
};
use libc::{sockaddr_ll, sockaddr_nl};
use crate::{Error, Result};
/// Represents socket variants on a Linux system.
pub enum UdevSocket {
SocketAddrV4(SocketAddrV4),
SocketAddrV6(SocketAddrV6),
Unix(UnixStream),
Netlink(sockaddr_nl),
Physical(sockaddr_ll),
}
impl UdevSocket {
/// Gets the kernel-provided PID for the socket.
pub fn pid(&self) -> Result<u32> {
match self {
Self::Netlink(socket) => Ok(socket.nl_pid),
_ => Err(Error::Udev("socket: PID unsupported".into())),
}
}
/// Creates a new [UdevSocket] for a [`sockaddr_nl`] Netlink socket type.
pub fn new_nl(family: i32, pid: u32, groups: u32) -> Self {
// SAFETY: `sockaddr_nl` is a well-aligned struct, so zeroing its memory results in a valid
// stack allocation.
let mut nl = unsafe { mem::zeroed::<sockaddr_nl>() };
nl.nl_family = family as u16;
nl.nl_pid = pid;
nl.nl_groups = groups;
Self::Netlink(nl)
}
/// Gets the [UdevSocket] as a reference to a [`sockaddr_nl`](libc::sockaddr_nl).
///
/// Returns `Err(Error)` if not a [UdevSocket::Netlink] variant.
pub fn as_nl(&self) -> Result<&sockaddr_nl> {
match self {
Self::Netlink(nl) => Ok(nl),
_ => Err(Error::Udev("socket: expected sockaddr_nl".into())),
}
}
/// Gets the [UdevSocket] as a mutable reference to a [`sockaddr_nl`](libc::sockaddr_nl).
///
/// Returns `Err(Error)` if not a [UdevSocket::Netlink] variant.
pub fn as_nl_mut(&mut self) -> Result<&mut sockaddr_nl> {
match self {
Self::Netlink(nl) => Ok(nl),
_ => Err(Error::Udev("socket: expected sockaddr_nl".into())),
}
}
/// Gets the [UdevSocket] as a const pointer to a [`sockaddr_nl`](libc::sockaddr_nl).
///
/// Returns `Err(Error)` if not a [UdevSocket::Netlink] variant.
pub fn as_nl_ptr(&self) -> Result<*const sockaddr_nl> {
match self {
Self::Netlink(nl) => Ok(nl as *const _),
_ => Err(Error::Udev("socket: expected sockaddr_nl".into())),
}
}
/// Gets the [UdevSocket] as a const pointer to a [`sockaddr_nl`](libc::sockaddr_nl).
///
/// Returns `Err(Error)` if not a [UdevSocket::Netlink] variant.
pub fn as_nl_ptr_mut(&mut self) -> Result<*mut sockaddr_nl> {
match self {
Self::Netlink(nl) => Ok(nl as *mut _),
_ => Err(Error::Udev("socket: expected sockaddr_nl".into())),
}
}
}