netlink_packet_sock_diag/inet/request.rs
1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use netlink_packet_utils::traits::{Emitable, Parseable, ParseableParametrized};
5use netlink_packet_utils::{DecodeError, buffer};
6
7use crate::constants::*;
8use crate::inet::{SocketId, SocketIdBuffer};
9
10pub const REQUEST_LEN: usize = 56;
11
12buffer!(InetRequestBuffer(REQUEST_LEN) {
13 family: (u8, 0),
14 protocol: (u8, 1),
15 extensions: (u8, 2),
16 pad: (u8, 3),
17 states: (u32, 4..8),
18 socket_id: (slice, 8..56),
19});
20
21/// A request for Ipv4 and Ipv6 sockets
22#[derive(Debug, PartialEq, Eq, Clone)]
23pub struct InetRequest {
24 /// The address family, either `AF_INET` or `AF_INET6`
25 pub family: u8,
26 /// The IP protocol. This field should be set to one of the
27 /// `IPPROTO_*` constants
28 pub protocol: u8,
29 /// Set of flags defining what kind of extended information to
30 /// report. Each requested kind of information is reported back as
31 /// a netlink attribute.
32 pub extensions: ExtensionFlags,
33 /// Bitmask that defines a filter of TCP socket states
34 pub states: StateFlags,
35 /// A socket ID object that is used in dump requests, in queries
36 /// about individual sockets, and is reported back in each
37 /// response.
38 ///
39 /// Unlike UNIX domain sockets, IPv4 and IPv6 sockets are
40 /// identified using addresses and ports.
41 pub socket_id: SocketId,
42}
43
44bitflags! {
45 /// Bitmask that defines a filter of TCP socket states
46 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
47 pub struct StateFlags: u32 {
48 /// (server and client) represents an open connection,
49 /// data received can be delivered to the user. The normal
50 /// state for the data transfer phase of the connection.
51 const ESTABLISHED = 1 << TCP_ESTABLISHED ;
52 /// (client) represents waiting for a matching connection
53 /// request after having sent a connection request.
54 const SYN_SENT = 1 <<TCP_SYN_SENT ;
55 /// (server) represents waiting for a confirming connection
56 /// request acknowledgment after having both received and sent
57 /// a connection request.
58 const SYN_RECV = 1 << TCP_SYN_RECV ;
59 /// (both server and client) represents waiting for a
60 /// connection termination request from the remote TCP, or an
61 /// acknowledgment of the connection termination request
62 /// previously sent.
63 const FIN_WAIT1 = 1 << TCP_FIN_WAIT1 ;
64 /// (both server and client) represents waiting for a
65 /// connection termination request from the remote TCP.
66 const FIN_WAIT2 = 1 << TCP_FIN_WAIT2 ;
67 /// (either server or client) represents waiting for enough
68 /// time to pass to be sure the remote TCP received the
69 /// acknowledgment of its connection termination request.
70 const TIME_WAIT = 1 << TCP_TIME_WAIT ;
71 /// (both server and client) represents no connection state at
72 /// all.
73 const CLOSE = 1 << TCP_CLOSE ;
74 /// (both server and client) represents waiting for a
75 /// connection termination request from the local user.
76 const CLOSE_WAIT = 1 << TCP_CLOSE_WAIT ;
77 /// (both server and client) represents waiting for an
78 /// acknowledgment of the connection termination request
79 /// previously sent to the remote TCP (which includes an
80 /// acknowledgment of its connection termination request).
81 const LAST_ACK = 1 << TCP_LAST_ACK ;
82 /// (server) represents waiting for a connection request from
83 /// any remote TCP and port.
84 const LISTEN = 1 << TCP_LISTEN ;
85 /// (both server and client) represents waiting for a
86 /// connection termination request acknowledgment from the
87 /// remote TCP.
88 const CLOSING = 1 << TCP_CLOSING ;
89 }
90}
91
92bitflags! {
93 /// This is a set of flags defining what kind of extended
94 /// information to report.
95 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
96 pub struct ExtensionFlags: u8 {
97 const MEMINFO = 1 << (INET_DIAG_MEMINFO - 1);
98 const INFO = 1 << (INET_DIAG_INFO - 1);
99 const VEGASINFO = 1 << (INET_DIAG_VEGASINFO - 1);
100 const CONG = 1 << (INET_DIAG_CONG - 1);
101 const TOS = 1 << (INET_DIAG_TOS - 1);
102 const TCLASS = 1 << (INET_DIAG_TCLASS - 1);
103 const SKMEMINFO = 1 << (INET_DIAG_SKMEMINFO - 1);
104 const SHUTDOWN = 1 << (INET_DIAG_SHUTDOWN - 1);
105 }
106}
107
108impl<'a, T: AsRef<[u8]> + ?Sized + 'a> Parseable<InetRequestBuffer<&'a T>> for InetRequest {
109 type Error = DecodeError;
110 fn parse(buf: &InetRequestBuffer<&'a T>) -> Result<Self, DecodeError> {
111 let err = "invalid socket_id value";
112 let socket_id = SocketId::parse_with_param(
113 &SocketIdBuffer::new(&buf.socket_id()).context(err)?,
114 buf.family(),
115 )
116 .context(err)?;
117
118 Ok(Self {
119 family: buf.family(),
120 protocol: buf.protocol(),
121 extensions: ExtensionFlags::from_bits_truncate(buf.extensions()),
122 states: StateFlags::from_bits_truncate(buf.states()),
123 socket_id,
124 })
125 }
126}
127
128impl Emitable for InetRequest {
129 fn buffer_len(&self) -> usize {
130 REQUEST_LEN
131 }
132
133 fn emit(&self, buf: &mut [u8]) {
134 let mut buf = InetRequestBuffer::new_unchecked(buf);
135 buf.set_family(self.family);
136 buf.set_protocol(self.protocol);
137 buf.set_extensions(self.extensions.bits());
138 buf.set_pad(0);
139 buf.set_states(self.states.bits());
140 self.socket_id.emit(buf.socket_id_mut())
141 }
142}