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}