netlink_packet_sock_diag/unix/
response.rs1use std::convert::TryFrom;
4
5use anyhow::Context;
6use netlink_packet_utils::nla::{NlaBuffer, NlasIterator};
7use netlink_packet_utils::traits::{Emitable, Parseable};
8use netlink_packet_utils::{DecodeError, buffer};
9use smallvec::SmallVec;
10
11use crate::constants::*;
12use crate::unix::nlas::{MemInfo, Nla};
13
14pub const UNIX_RESPONSE_HEADER_LEN: usize = 16;
15
16buffer!(UnixResponseBuffer(UNIX_RESPONSE_HEADER_LEN) {
17 family: (u8, 0),
18 kind: (u8, 1),
19 state: (u8, 2),
20 pad: (u8, 3),
21 inode: (u32, 4..8),
22 cookie: (slice, 8..UNIX_RESPONSE_HEADER_LEN),
23 payload: (slice, UNIX_RESPONSE_HEADER_LEN..),
24});
25
26#[derive(Debug, PartialEq, Eq, Clone)]
28pub struct UnixResponseHeader {
29 pub kind: u8,
31 pub state: u8,
37 pub inode: u32,
39 pub cookie: [u8; 8],
40}
41
42impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<UnixResponseBuffer<&'a T>> for UnixResponseHeader {
43 type Error = DecodeError;
44 fn parse(buf: &UnixResponseBuffer<&'a T>) -> Result<Self, DecodeError> {
45 Ok(Self {
46 kind: buf.kind(),
47 state: buf.state(),
48 inode: buf.inode(),
49 cookie: TryFrom::try_from(buf.cookie()).unwrap(),
52 })
53 }
54}
55
56impl Emitable for UnixResponseHeader {
57 fn buffer_len(&self) -> usize {
58 UNIX_RESPONSE_HEADER_LEN
59 }
60
61 fn emit(&self, buf: &mut [u8]) {
62 let mut buf = UnixResponseBuffer::new_unchecked(buf);
63 buf.set_family(AF_UNIX);
64 buf.set_kind(self.kind);
65 buf.set_state(self.state);
66 buf.set_pad(0);
67 buf.set_inode(self.inode);
68 buf.cookie_mut().copy_from_slice(&self.cookie[..]);
69 }
70}
71
72#[derive(Debug, PartialEq, Eq, Clone)]
73pub struct UnixResponse {
74 pub header: UnixResponseHeader,
75 pub nlas: SmallVec<[Nla; 8]>,
76}
77
78impl UnixResponse {
79 pub fn peer(&self) -> Option<u32> {
80 self.nlas.iter().find_map(
81 |nla| {
82 if let Nla::Peer(inode) = nla { Some(*inode) } else { None }
83 },
84 )
85 }
86
87 pub fn name(&self) -> Option<&String> {
88 self.nlas.iter().find_map(|nla| if let Nla::Name(name) = nla { Some(name) } else { None })
89 }
90
91 pub fn pending_connections(&self) -> Option<&[u32]> {
92 self.nlas.iter().find_map(|nla| {
93 if let Nla::PendingConnections(connections) = nla {
94 Some(&connections[..])
95 } else {
96 None
97 }
98 })
99 }
100
101 fn mem_info(&self) -> Option<MemInfo> {
102 self.nlas
103 .iter()
104 .find_map(|nla| if let Nla::MemInfo(mem_info) = nla { Some(*mem_info) } else { None })
105 }
106
107 pub fn shutdown_state(&self) -> Option<u8> {
108 self.nlas.iter().find_map(|nla| {
109 if let Nla::Shutdown(shutdown_state) = nla { Some(*shutdown_state) } else { None }
110 })
111 }
112
113 fn receive_queue_length(&self) -> Option<(u32, u32)> {
114 self.nlas.iter().find_map(|nla| {
115 if let Nla::ReceiveQueueLength(x, y) = nla { Some((*x, *y)) } else { None }
116 })
117 }
118
119 pub fn number_of_pending_connection(&self) -> Option<u32> {
120 if self.header.state == TCP_LISTEN {
121 self.receive_queue_length().map(|(n, _)| n)
122 } else {
123 None
124 }
125 }
126
127 pub fn max_number_of_pending_connection(&self) -> Option<u32> {
128 if self.header.state == TCP_LISTEN {
129 self.receive_queue_length().map(|(_, n)| n)
130 } else {
131 None
132 }
133 }
134
135 pub fn receive_queue_size(&self) -> Option<u32> {
136 if self.header.state == TCP_LISTEN {
137 None
138 } else {
139 self.receive_queue_length().map(|(n, _)| n)
140 }
141 }
142
143 pub fn send_queue_size(&self) -> Option<u32> {
144 if self.header.state == TCP_LISTEN {
145 self.receive_queue_length().map(|(n, _)| n)
146 } else {
147 None
148 }
149 }
150
151 pub fn max_datagram_size(&self) -> Option<u32> {
152 self.mem_info().map(|mem_info| mem_info.max_datagram_size)
153 }
154
155 pub fn memory_used_for_outgoing_data(&self) -> Option<u32> {
156 self.mem_info().map(|mem_info| mem_info.alloc)
157 }
158}
159
160impl<'a, T: AsRef<[u8]> + ?Sized> UnixResponseBuffer<&'a T> {
161 pub fn nlas(&self) -> impl Iterator<Item = Result<NlaBuffer<&'a [u8]>, DecodeError>> {
162 NlasIterator::new(self.payload()).map(|nla| nla.map_err(Into::into))
163 }
164}
165
166impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<UnixResponseBuffer<&'a T>> for SmallVec<[Nla; 8]> {
167 type Error = DecodeError;
168 fn parse(buf: &UnixResponseBuffer<&'a T>) -> Result<Self, DecodeError> {
169 let mut nlas = smallvec![];
170 for nla_buf in buf.nlas() {
171 nlas.push(Nla::parse(&nla_buf?)?);
172 }
173 Ok(nlas)
174 }
175}
176
177impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<UnixResponseBuffer<&'a T>> for UnixResponse {
178 type Error = DecodeError;
179 fn parse(buf: &UnixResponseBuffer<&'a T>) -> Result<Self, DecodeError> {
180 let header =
181 UnixResponseHeader::parse(buf).context("failed to parse inet response header")?;
182 let nlas =
183 SmallVec::<[Nla; 8]>::parse(buf).context("failed to parse inet response NLAs")?;
184 Ok(UnixResponse { header, nlas })
185 }
186}
187
188impl Emitable for UnixResponse {
189 fn buffer_len(&self) -> usize {
190 self.header.buffer_len() + self.nlas.as_slice().buffer_len()
191 }
192
193 fn emit(&self, buffer: &mut [u8]) {
194 self.header.emit(buffer);
195 self.nlas.as_slice().emit(&mut buffer[self.header.buffer_len()..]);
196 }
197}