netlink_packet_sock_diag/inet/
response.rs

1// SPDX-License-Identifier: MIT
2
3use std::time::Duration;
4
5use anyhow::Context;
6use netlink_packet_utils::nla::{NlaBuffer, NlasIterator};
7use netlink_packet_utils::traits::{Emitable, Parseable, ParseableParametrized};
8use netlink_packet_utils::{DecodeError, buffer};
9use smallvec::SmallVec;
10
11use crate::inet::nlas::Nla;
12use crate::inet::{SocketId, SocketIdBuffer};
13
14/// The type of timer that is currently active for a TCP socket.
15#[derive(Debug, PartialEq, Eq, Clone)]
16pub enum Timer {
17    /// A retransmit timer
18    Retransmit(Duration, u8),
19    /// A keep-alive timer
20    KeepAlive(Duration),
21    /// A `TIME_WAIT` timer
22    TimeWait,
23    /// A zero window probe timer
24    Probe(Duration),
25}
26
27pub const RESPONSE_LEN: usize = 72;
28
29buffer!(InetResponseBuffer(RESPONSE_LEN) {
30    family: (u8, 0),
31    state: (u8, 1),
32    timer: (u8, 2),
33    retransmits: (u8, 3),
34    socket_id: (slice, 4..52),
35    expires: (u32, 52..56),
36    recv_queue: (u32, 56..60),
37    send_queue: (u32, 60..64),
38    uid: (u32, 64..68),
39    inode: (u32, 68..72),
40    payload: (slice, RESPONSE_LEN..),
41});
42
43/// The response to a query for IPv4 or IPv6 sockets
44#[derive(Debug, PartialEq, Eq, Clone)]
45pub struct InetResponseHeader {
46    /// This should be set to either `AF_INET` or `AF_INET6` for IPv4
47    /// or IPv6 sockets respectively.
48    pub family: u8,
49
50    /// The socket state.
51    pub state: u8,
52
53    /// For TCP sockets, this field describes the type of timer
54    /// that is currently active for the socket.
55    pub timer: Option<Timer>,
56
57    /// The socket ID object.
58    pub socket_id: SocketId,
59
60    /// For listening sockets: the number of pending connections. For
61    /// other sockets: the amount of data in the incoming queue.
62    pub recv_queue: u32,
63
64    /// For listening sockets: the backlog length. For other sockets:
65    /// the amount of memory available for sending.
66    pub send_queue: u32,
67
68    /// Socket owner UID.
69    pub uid: u32,
70
71    /// Socket inode number.
72    pub inode: u32,
73}
74
75impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<InetResponseBuffer<&'a T>> for InetResponseHeader {
76    type Error = DecodeError;
77    fn parse(buf: &InetResponseBuffer<&'a T>) -> Result<Self, DecodeError> {
78        let err = "invalid socket_id value";
79        let socket_id = SocketId::parse_with_param(
80            &SocketIdBuffer::new(&buf.socket_id()).context(err)?,
81            buf.family(),
82        )
83        .context(err)?;
84
85        let timer = match buf.timer() {
86            1 => {
87                let expires = Duration::from_millis(buf.expires() as u64);
88                let retransmits = buf.retransmits();
89                Some(Timer::Retransmit(expires, retransmits))
90            }
91            2 => {
92                let expires = Duration::from_millis(buf.expires() as u64);
93                Some(Timer::KeepAlive(expires))
94            }
95            3 => Some(Timer::TimeWait),
96            4 => {
97                let expires = Duration::from_millis(buf.expires() as u64);
98                Some(Timer::Probe(expires))
99            }
100            _ => None,
101        };
102
103        Ok(Self {
104            family: buf.family(),
105            state: buf.state(),
106            timer,
107            socket_id,
108            recv_queue: buf.recv_queue(),
109            send_queue: buf.send_queue(),
110            uid: buf.uid(),
111            inode: buf.inode(),
112        })
113    }
114}
115
116impl Emitable for InetResponseHeader {
117    fn buffer_len(&self) -> usize {
118        RESPONSE_LEN
119    }
120
121    fn emit(&self, buf: &mut [u8]) {
122        let mut buf = InetResponseBuffer::new_unchecked(buf);
123        buf.set_family(self.family);
124        buf.set_state(self.state);
125        match self.timer {
126            Some(Timer::Retransmit(expires, retransmits)) => {
127                buf.set_timer(1);
128                buf.set_expires((expires.as_millis() & 0xffff_ffff) as u32);
129                buf.set_retransmits(retransmits);
130            }
131            Some(Timer::KeepAlive(expires)) => {
132                buf.set_timer(2);
133                buf.set_expires((expires.as_millis() & 0xffff_ffff) as u32);
134                buf.set_retransmits(0);
135            }
136            Some(Timer::TimeWait) => {
137                buf.set_timer(3);
138                buf.set_expires(0);
139                buf.set_retransmits(0);
140            }
141            Some(Timer::Probe(expires)) => {
142                buf.set_timer(4);
143                buf.set_expires((expires.as_millis() & 0xffff_ffff) as u32);
144                buf.set_retransmits(0);
145            }
146            None => {
147                buf.set_timer(0);
148                buf.set_expires(0);
149                buf.set_retransmits(0);
150            }
151        }
152        buf.set_recv_queue(self.recv_queue);
153        buf.set_send_queue(self.send_queue);
154        buf.set_uid(self.uid);
155        buf.set_inode(self.inode);
156        self.socket_id.emit(buf.socket_id_mut())
157    }
158}
159
160#[derive(Debug, PartialEq, Eq, Clone)]
161pub struct InetResponse {
162    pub header: InetResponseHeader,
163    pub nlas: SmallVec<[Nla; 8]>,
164}
165
166impl<'a, T: AsRef<[u8]> + ?Sized> InetResponseBuffer<&'a T> {
167    pub fn nlas(&self) -> impl Iterator<Item = Result<NlaBuffer<&'a [u8]>, DecodeError>> {
168        NlasIterator::new(self.payload()).map(|res| res.map_err(Into::into))
169    }
170}
171
172impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<InetResponseBuffer<&'a T>> for SmallVec<[Nla; 8]> {
173    type Error = DecodeError;
174    fn parse(buf: &InetResponseBuffer<&'a T>) -> Result<Self, DecodeError> {
175        let mut nlas = smallvec![];
176        for nla_buf in buf.nlas() {
177            nlas.push(Nla::parse(&nla_buf?)?);
178        }
179        Ok(nlas)
180    }
181}
182
183impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<InetResponseBuffer<&'a T>> for InetResponse {
184    type Error = DecodeError;
185    fn parse(buf: &InetResponseBuffer<&'a T>) -> Result<Self, DecodeError> {
186        let header =
187            InetResponseHeader::parse(buf).context("failed to parse inet response header")?;
188        let nlas =
189            SmallVec::<[Nla; 8]>::parse(buf).context("failed to parse inet response NLAs")?;
190        Ok(InetResponse { header, nlas })
191    }
192}
193
194impl Emitable for InetResponse {
195    fn buffer_len(&self) -> usize {
196        self.header.buffer_len() + self.nlas.as_slice().buffer_len()
197    }
198
199    fn emit(&self, buffer: &mut [u8]) {
200        self.header.emit(buffer);
201        self.nlas.as_slice().emit(&mut buffer[self.header.buffer_len()..]);
202    }
203}