netlink_packet_sock_diag/unix/
request.rs

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