Skip to main content

netlink_packet_sock_diag/inet/
request.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer, NlasIterator};
5use netlink_packet_utils::traits::{Emitable, Parseable};
6use netlink_packet_utils::{DecodeError, ParseableParametrized, buffer};
7use smallvec::SmallVec;
8
9use crate::constants::*;
10use crate::inet::{SocketId, SocketIdBuffer};
11
12pub const REQUEST_LEN: usize = 56;
13
14buffer!(InetRequestBuffer(REQUEST_LEN) {
15    family: (u8, 0),
16    protocol: (u8, 1),
17    extensions: (u8, 2),
18    pad: (u8, 3),
19    states: (u32, 4..8),
20    socket_id: (slice, 8..56),
21    payload: (slice, REQUEST_LEN..),
22});
23
24#[derive(Debug, PartialEq, Eq, Clone)]
25pub enum RequestNla {
26    /// The raw bytes of a bytecode program. See [`crate::inet::bytecode`] for
27    /// parsing and serializing bytecode programs.
28    Bytecode(Vec<u8>),
29    Other(DefaultNla),
30}
31
32impl Nla for RequestNla {
33    fn value_len(&self) -> usize {
34        match self {
35            Self::Bytecode(v) => v.len(),
36            Self::Other(attr) => attr.value_len(),
37        }
38    }
39
40    fn kind(&self) -> u16 {
41        match self {
42            Self::Bytecode(_) => INET_DIAG_REQ_BYTECODE,
43            Self::Other(attr) => attr.kind(),
44        }
45    }
46
47    fn emit_value(&self, buffer: &mut [u8]) {
48        match self {
49            Self::Bytecode(v) => buffer[..v.len()].copy_from_slice(&v[..]),
50            Self::Other(attr) => attr.emit_value(buffer),
51        }
52    }
53}
54
55impl<'a, T: AsRef<[u8]> + ?Sized> InetRequestBuffer<&'a T> {
56    pub fn nlas(&self) -> impl Iterator<Item = Result<NlaBuffer<&'a [u8]>, DecodeError>> {
57        NlasIterator::new(self.payload()).map(|res| res.map_err(Into::into))
58    }
59}
60
61impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for RequestNla {
62    type Error = DecodeError;
63    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
64        let payload = buf.value();
65        Ok(match buf.kind() {
66            INET_DIAG_REQ_BYTECODE => Self::Bytecode(payload.to_vec()),
67            kind => {
68                Self::Other(DefaultNla::parse(buf).context(format!("unknown NLA type {kind}"))?)
69            }
70        })
71    }
72}
73
74/// A request for Ipv4 and Ipv6 sockets
75#[derive(Debug, PartialEq, Eq, Clone)]
76pub struct InetRequest {
77    /// The address family, either `AF_INET` or `AF_INET6`
78    pub family: u8,
79    /// The IP protocol. This field should be set to one of the
80    /// `IPPROTO_*` constants
81    pub protocol: u8,
82    /// Set of flags defining what kind of extended information to
83    /// report. Each requested kind of information is reported back as
84    /// a netlink attribute.
85    pub extensions: ExtensionFlags,
86    /// Bitmask that defines a filter of TCP socket states
87    pub states: StateFlags,
88    /// A socket ID object that is used in dump requests, in queries
89    /// about individual sockets, and is reported back in each
90    /// response.
91    ///
92    /// Unlike UNIX domain sockets, IPv4 and IPv6 sockets are
93    /// identified using addresses and ports.
94    pub socket_id: SocketId,
95    pub nlas: SmallVec<[RequestNla; 4]>,
96}
97
98bitflags! {
99    /// Bitmask that defines a filter of TCP socket states
100    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
101    pub struct StateFlags: u32 {
102        /// (server and client) represents an open connection,
103        /// data received can be delivered to the user. The normal
104        /// state for the data transfer phase of the connection.
105        const ESTABLISHED = 1 << TCP_ESTABLISHED ;
106        /// (client) represents waiting for a matching connection
107        /// request after having sent a connection request.
108        const SYN_SENT = 1 <<TCP_SYN_SENT ;
109        /// (server) represents waiting for a confirming connection
110        /// request acknowledgment after having both received and sent
111        /// a connection request.
112        const SYN_RECV = 1 << TCP_SYN_RECV ;
113        /// (both server and client) represents waiting for a
114        /// connection termination request from the remote TCP, or an
115        /// acknowledgment of the connection termination request
116        /// previously sent.
117        const FIN_WAIT1 = 1 << TCP_FIN_WAIT1 ;
118        /// (both server and client) represents waiting for a
119        /// connection termination request from the remote TCP.
120        const FIN_WAIT2 = 1 << TCP_FIN_WAIT2 ;
121        /// (either server or client) represents waiting for enough
122        /// time to pass to be sure the remote TCP received the
123        /// acknowledgment of its connection termination request.
124        const TIME_WAIT = 1 << TCP_TIME_WAIT ;
125        /// (both server and client) represents no connection state at
126        /// all.
127        const CLOSE = 1 << TCP_CLOSE ;
128        /// (both server and client) represents waiting for a
129        /// connection termination request from the local user.
130        const CLOSE_WAIT = 1 << TCP_CLOSE_WAIT ;
131        /// (both server and client) represents waiting for an
132        /// acknowledgment of the connection termination request
133        /// previously sent to the remote TCP (which includes an
134        /// acknowledgment of its connection termination request).
135        const LAST_ACK = 1 << TCP_LAST_ACK ;
136        /// (server) represents waiting for a connection request from
137        /// any remote TCP and port.
138        const LISTEN = 1 << TCP_LISTEN ;
139        /// (both server and client) represents waiting for a
140        /// connection termination request acknowledgment from the
141        /// remote TCP.
142        const CLOSING = 1 << TCP_CLOSING ;
143    }
144}
145
146bitflags! {
147    /// This is a set of flags defining what kind of extended
148    /// information to report.
149    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
150    pub struct ExtensionFlags: u8 {
151        const MEMINFO = 1 << (INET_DIAG_MEMINFO - 1);
152        const INFO = 1 << (INET_DIAG_INFO - 1);
153        const VEGASINFO = 1 << (INET_DIAG_VEGASINFO - 1);
154        const CONG = 1 << (INET_DIAG_CONG - 1);
155        const TOS = 1 << (INET_DIAG_TOS - 1);
156        const TCLASS = 1 << (INET_DIAG_TCLASS - 1);
157        const SKMEMINFO = 1 << (INET_DIAG_SKMEMINFO - 1);
158        const SHUTDOWN = 1 << (INET_DIAG_SHUTDOWN - 1);
159    }
160}
161
162impl<'a, T: AsRef<[u8]> + ?Sized + 'a> Parseable<InetRequestBuffer<&'a T>> for InetRequest {
163    type Error = DecodeError;
164    fn parse(buf: &InetRequestBuffer<&'a T>) -> Result<Self, DecodeError> {
165        let err = "invalid socket_id value";
166        let socket_id = SocketId::parse_with_param(
167            &SocketIdBuffer::new(&buf.socket_id()).context(err)?,
168            buf.family(),
169        )
170        .context(err)?;
171
172        let mut nlas = SmallVec::new();
173        for nla_buf in buf.nlas() {
174            nlas.push(RequestNla::parse(&nla_buf?)?);
175        }
176
177        Ok(Self {
178            family: buf.family(),
179            protocol: buf.protocol(),
180            extensions: ExtensionFlags::from_bits_truncate(buf.extensions()),
181            states: StateFlags::from_bits_truncate(buf.states()),
182            socket_id,
183            nlas,
184        })
185    }
186}
187
188impl Emitable for InetRequest {
189    fn buffer_len(&self) -> usize {
190        REQUEST_LEN + self.nlas.as_slice().buffer_len()
191    }
192
193    fn emit(&self, buf: &mut [u8]) {
194        let mut buf = InetRequestBuffer::new_unchecked(buf);
195        buf.set_family(self.family);
196        buf.set_protocol(self.protocol);
197        buf.set_extensions(self.extensions.bits());
198        buf.set_pad(0);
199        buf.set_states(self.states.bits());
200        self.socket_id.emit(buf.socket_id_mut());
201        self.nlas.as_slice().emit(&mut buf.payload_mut());
202    }
203}