netlink_packet_sock_diag/unix/
request.rs

1// SPDX-License-Identifier: MIT
2
3use std::convert::TryFrom;
4
5use netlink_packet_utils::traits::{Emitable, Parseable};
6use netlink_packet_utils::{DecodeError, buffer};
7
8use crate::constants::*;
9
10pub const UNIX_REQUEST_LEN: usize = 24;
11
12buffer!(UnixRequestBuffer(UNIX_REQUEST_LEN) {
13    // The address family; it should be set to `AF_UNIX`
14    family: (u8, 0),
15    // This field should be set to `0`
16    protocol: (u8, 1),
17    // This field should be set to `0`
18    pad: (u16, 2..4),
19    // This is a bit mask that defines a filter of sockets
20    // states. Only those sockets whose states are in this mask will
21    // be reported. Ignored when querying for an individual
22    // socket. Supported values are:
23    //
24    // ```no_rust
25    // 1 << UNIX_ESTABLISHED
26    // 1 << UNIX_LISTEN
27    // ```
28    state_flags: (u32, 4..8),
29    // This is an inode number when querying for an individual
30    // socket. Ignored when querying for a list of sockets.
31    inode: (u32, 8..12),
32    // This is a set of flags defining what kind of information to
33    // report. Supported values are the `UDIAG_SHOW_*` constants.
34    show_flags: (u32, 12..16),
35    // This is an array of opaque identifiers that could be used
36    // along with udiag_ino to specify an individual socket. It is
37    // ignored when querying for a list of sockets, as well as when
38    // all its elements are set to `0xff`.
39    cookie: (slice, 16..UNIX_REQUEST_LEN),
40});
41
42/// The request for UNIX domain sockets
43#[derive(Debug, PartialEq, Eq, Clone)]
44pub struct UnixRequest {
45    /// This is a bit mask that defines a filter of sockets states.
46    ///
47    /// Only those sockets whose states are in this mask will be reported.
48    /// Ignored when querying for an individual socket.
49    pub state_flags: StateFlags,
50    /// This is an inode number when querying for an individual socket.
51    ///
52    /// Ignored when querying for a list of sockets.
53    pub inode: u32,
54    /// This is a set of flags defining what kind of information to report.
55    ///
56    /// Each requested kind of information is reported back as a netlink
57    /// attribute
58    pub show_flags: ShowFlags,
59    /// This is an opaque identifiers that could be used to specify an
60    /// individual socket.
61    pub cookie: [u8; 8],
62}
63
64bitflags! {
65    /// Bitmask that defines a filter of UNIX socket states
66    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
67    pub struct StateFlags: u32 {
68        const ESTABLISHED = 1 << TCP_ESTABLISHED;
69        const LISTEN = 1 << TCP_LISTEN;
70    }
71}
72
73bitflags! {
74    /// Bitmask that defines what kind of information to
75    /// report. Supported values are the `UDIAG_SHOW_*` constants.
76    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
77    pub struct ShowFlags: u32 {
78        const NAME = UDIAG_SHOW_NAME;
79        const VFS = UDIAG_SHOW_VFS;
80        const PEER = UDIAG_SHOW_PEER;
81        const ICONS = UDIAG_SHOW_ICONS;
82        const RQLEN = UDIAG_SHOW_RQLEN;
83        const MEMINFO = UDIAG_SHOW_MEMINFO;
84    }
85}
86
87impl<'a, T: AsRef<[u8]> + ?Sized + 'a> Parseable<UnixRequestBuffer<&'a T>> for UnixRequest {
88    type Error = DecodeError;
89    fn parse(buf: &UnixRequestBuffer<&'a T>) -> Result<Self, DecodeError> {
90        Ok(Self {
91            state_flags: StateFlags::from_bits_truncate(buf.state_flags()),
92            inode: buf.inode(),
93            show_flags: ShowFlags::from_bits_truncate(buf.show_flags()),
94            // Unwrapping is safe because UnixRequestBuffer::cookie()
95            // returns a slice of exactly 8 bytes.
96            cookie: TryFrom::try_from(buf.cookie()).unwrap(),
97        })
98    }
99}
100
101impl Emitable for UnixRequest {
102    fn buffer_len(&self) -> usize {
103        UNIX_REQUEST_LEN
104    }
105
106    fn emit(&self, buf: &mut [u8]) {
107        let mut buffer = UnixRequestBuffer::new_unchecked(buf);
108        buffer.set_family(AF_UNIX);
109        buffer.set_protocol(0);
110        buffer.set_state_flags(self.state_flags.bits());
111        buffer.set_inode(self.inode);
112        buffer.set_pad(0);
113        buffer.set_show_flags(self.show_flags.bits());
114        buffer.cookie_mut().copy_from_slice(&self.cookie[..]);
115    }
116}