1#![doc = "Internet socket diagnostics\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &str = "inet-diag";
17pub const PROTONAME_CSTR: &CStr = c"inet-diag";
18pub const PROTONUM: u16 = 4u16;
19pub const TCPDIAG_GETSOCK_CONST: u64 = 18u64;
20pub const DCCPDIAG_GETSOCK_CONST: u64 = 19u64;
21pub const GETSOCK_MAX_CONST: u64 = 24u64;
22pub const NOCOOKIE_CONST: u64 = 4294967295u64;
23#[doc = "Socket identity"]
24#[doc = "SOCK\\_RAW sockets require the underlied protocol to be additionally\nspecified so we can use @pad member for this, but we can't rename it\nbecause userspace programs still may depend on this name\\. Instead lets\nuse another structure definition as an alias for struct\n@inet\\_diag\\_req\\_v2\\.\n"]
25#[doc = "Base info structure\\. It contains socket identity (addrs/ports/cookie)\nand, alas, the information shown by netstat\\.\n"]
26#[doc = "Bytecode is sequence of 4 byte commands followed by variable arguments\\.\nAll the commands identified by \"code\" are conditional jumps forward: to\noffset cc\\+\"yes\" (bytes) or to offset cc\\+\"no\" (bytes)\\. \"yes\" is supposed\nto be length of the command and its arguments (in bytes)\\.\n\nTermination condition is to land excactly on a len'th instruction (on\naddress of one after the last one), overshooting means an unsucessfull\ntermination\\.\n\nIf you reading this, for your own sanity, I advice you to first try\nreverse\\-lookup on the \\`ss\\` command with filters you need, and copy\nbytecode from there\\.\n"]
27#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
28#[derive(Debug, Clone, Copy)]
29pub enum BytecodeOpCode {
30 Nop = 0,
31 #[doc = "unconditional jump\\. \"no\" value is ignored\\."]
32 Jmp = 1,
33 #[doc = "sock\\.sport >= next\\_instruction\\.no (big endian)"]
34 SportGe = 2,
35 #[doc = "sock\\.sport <= next\\_instruction\\.no (big endian)"]
36 SportLe = 3,
37 #[doc = "sock\\.dport >= next\\_instruction\\.no (big endian)"]
38 DportGe = 4,
39 #[doc = "sock\\.dport <= next\\_instruction\\.no (big endian)"]
40 DportLe = 5,
41 #[doc = "check if sock is NOT bound to a port by user,\ni\\.e\\. !(sk\\->userlocks & SOCK\\_BINDPORT\\_LOCK)\n"]
42 PortAuto = 6,
43 #[doc = "Check aginst source socket addr packed as hostcond struct (hc),\nfollowed by big\\-endian ipv4 or ipv6 address (yes, it's that cursed)\\.\n\nThe check equivalent to the following (in order):\n no if hc\\.port != \\-1 && hc\\.port != sock\\.sport\n yes if hc\\.family == AF\\_INET && sock\\.family == AF\\_INET6\n && &sock\\.saddr\\_u32\\[0\\.\\.3\\] == &\\[0, 0, 0xffff\\.to\\_be()\\]\n && bits\\_eq(&sock\\.saddr\\_u8\\[12\\.\\.\\], &hc\\.addr\\[\\.\\.\\], hc\\.prefix\\_len)\n no if hc\\.family != AF\\_UNSPEC && hc\\.family != family\n yes if hc\\.prefix\\_len == 0\n yes if bits\\_eq(&sock\\.addr\\[\\.\\.\\], &hc\\.addr\\[\\.\\.\\], hc\\.prefix\\_len)\n no\n\n See inet\\_diag\\_bc\\_run() in net/ipv4/inet\\_diag\\.c\n"]
44 SaddrCond = 7,
45 #[doc = "Check aginst source socket addr using hostcond struct\\.\nSame as \\`saddr\\-cond\\`, see its description\\.\n"]
46 DaddrCond = 8,
47 #[doc = "socket ifindex == next\\_instruction (native endian u32)"]
48 DevCond = 9,
49 #[doc = "Check check socket mark bits against markcond struct (mc)\\.\nThe check is equivalent to: sock\\.mark & mc\\.mask == mc\\.mark\n"]
50 MarkCond = 10,
51 #[doc = "sock\\.sport == next\\_instruction\\.no (big endian)"]
52 SportEq = 11,
53 #[doc = "sock\\.dport == next\\_instruction\\.no (big endian)"]
54 DportEq = 12,
55 #[doc = "sock\\.cgroup\\_id == next\\_2\\_instructions (native endian u64)"]
56 CgroupCond = 13,
57}
58impl BytecodeOpCode {
59 pub fn from_value(value: u64) -> Option<Self> {
60 Some(match value {
61 0 => Self::Nop,
62 1 => Self::Jmp,
63 2 => Self::SportGe,
64 3 => Self::SportLe,
65 4 => Self::DportGe,
66 5 => Self::DportLe,
67 6 => Self::PortAuto,
68 7 => Self::SaddrCond,
69 8 => Self::DaddrCond,
70 9 => Self::DevCond,
71 10 => Self::MarkCond,
72 11 => Self::SportEq,
73 12 => Self::DportEq,
74 13 => Self::CgroupCond,
75 _ => return None,
76 })
77 }
78}
79#[doc = "Host condition to be placed directly into bytecode\\.\nSocket address bytes should be appended right after this struct\\.\n"]
80#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
81#[derive(Debug, Clone, Copy)]
82pub enum SockoptFlag {
83 Recverr = 1 << 0,
84 IsIcsk = 1 << 1,
85 Freebind = 1 << 2,
86 Hdrincl = 1 << 3,
87 McLoop = 1 << 4,
88 Transparent = 1 << 5,
89 McAll = 1 << 6,
90 Nodefrag = 1 << 7,
91 BindAddressNoPort = 1 << 8,
92 RecverrRfc4884 = 1 << 9,
93 DeferConnect = 1 << 10,
94}
95impl SockoptFlag {
96 pub fn from_value(value: u64) -> Option<Self> {
97 Some(match value {
98 n if n == 1 << 0 => Self::Recverr,
99 n if n == 1 << 1 => Self::IsIcsk,
100 n if n == 1 << 2 => Self::Freebind,
101 n if n == 1 << 3 => Self::Hdrincl,
102 n if n == 1 << 4 => Self::McLoop,
103 n if n == 1 << 5 => Self::Transparent,
104 n if n == 1 << 6 => Self::McAll,
105 n if n == 1 << 7 => Self::Nodefrag,
106 n if n == 1 << 8 => Self::BindAddressNoPort,
107 n if n == 1 << 9 => Self::RecverrRfc4884,
108 n if n == 1 << 10 => Self::DeferConnect,
109 _ => return None,
110 })
111 }
112}
113#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
114#[derive(Debug, Clone, Copy)]
115pub enum TcpState {
116 Established = 1,
117 SynSent = 2,
118 SynRecv = 3,
119 FinWait1 = 4,
120 FinWait2 = 5,
121 TimeWait = 6,
122 Close = 7,
123 CloseWait = 8,
124 LastAck = 9,
125 Listen = 10,
126 #[doc = "Now a valid state"]
127 Closing = 11,
128 NewSynRecv = 12,
129 #[doc = "Pseudo\\-state for inet\\_diag"]
130 BoundInactive = 13,
131}
132impl TcpState {
133 pub fn from_value(value: u64) -> Option<Self> {
134 Some(match value {
135 1 => Self::Established,
136 2 => Self::SynSent,
137 3 => Self::SynRecv,
138 4 => Self::FinWait1,
139 5 => Self::FinWait2,
140 6 => Self::TimeWait,
141 7 => Self::Close,
142 8 => Self::CloseWait,
143 9 => Self::LastAck,
144 10 => Self::Listen,
145 11 => Self::Closing,
146 12 => Self::NewSynRecv,
147 13 => Self::BoundInactive,
148 _ => return None,
149 })
150 }
151}
152#[repr(C, packed(4))]
153pub struct Sockid {
154 pub _sport_be: u16,
155 pub _dport_be: u16,
156 pub src: [u8; 16usize],
157 pub dst: [u8; 16usize],
158 pub r#if: u32,
159 pub cookie: [u8; 8usize],
160}
161impl Clone for Sockid {
162 fn clone(&self) -> Self {
163 Self::new_from_array(*self.as_array())
164 }
165}
166#[doc = "Create zero-initialized struct"]
167impl Default for Sockid {
168 fn default() -> Self {
169 Self::new()
170 }
171}
172impl Sockid {
173 #[doc = "Create zero-initialized struct"]
174 pub fn new() -> Self {
175 Self::new_from_array([0u8; Self::len()])
176 }
177 #[doc = "Copy from contents from slice"]
178 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
179 if other.len() != Self::len() {
180 return None;
181 }
182 let mut buf = [0u8; Self::len()];
183 buf.clone_from_slice(other);
184 Some(Self::new_from_array(buf))
185 }
186 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
187 pub fn new_from_zeroed(other: &[u8]) -> Self {
188 let mut buf = [0u8; Self::len()];
189 let len = buf.len().min(other.len());
190 buf[..len].clone_from_slice(&other[..len]);
191 Self::new_from_array(buf)
192 }
193 pub fn new_from_array(buf: [u8; 48usize]) -> Self {
194 unsafe { std::mem::transmute(buf) }
195 }
196 pub fn as_slice(&self) -> &[u8] {
197 unsafe {
198 let ptr: *const u8 = std::mem::transmute(self as *const Self);
199 std::slice::from_raw_parts(ptr, Self::len())
200 }
201 }
202 pub fn from_slice(buf: &[u8]) -> &Self {
203 assert!(buf.len() >= Self::len());
204 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
205 unsafe { std::mem::transmute(buf.as_ptr()) }
206 }
207 pub fn as_array(&self) -> &[u8; 48usize] {
208 unsafe { std::mem::transmute(self) }
209 }
210 pub fn from_array(buf: &[u8; 48usize]) -> &Self {
211 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
212 unsafe { std::mem::transmute(buf) }
213 }
214 pub fn into_array(self) -> [u8; 48usize] {
215 unsafe { std::mem::transmute(self) }
216 }
217 pub const fn len() -> usize {
218 const _: () = assert!(std::mem::size_of::<Sockid>() == 48usize);
219 48usize
220 }
221 pub fn sport(&self) -> u16 {
222 u16::from_be(self._sport_be)
223 }
224 pub fn set_sport(&mut self, value: u16) {
225 self._sport_be = value.to_be();
226 }
227 pub fn dport(&self) -> u16 {
228 u16::from_be(self._dport_be)
229 }
230 pub fn set_dport(&mut self, value: u16) {
231 self._dport_be = value.to_be();
232 }
233}
234impl std::fmt::Debug for Sockid {
235 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
236 fmt.debug_struct("Sockid")
237 .field("sport", &self.sport())
238 .field("dport", &self.dport())
239 .field("src", &FormatHex(self.src))
240 .field("dst", &FormatHex(self.dst))
241 .field("if", &self.r#if)
242 .field("cookie", &FormatHex(self.cookie))
243 .finish()
244 }
245}
246#[repr(C, packed(4))]
247pub struct Req {
248 #[doc = "Family of addresses"]
249 pub family: u8,
250 pub src_len: u8,
251 pub dst_len: u8,
252 #[doc = "Query extended information"]
253 pub ext: u8,
254 pub sockid: Sockid,
255 #[doc = "States to dump\nAssociated type: [`TcpState`] (1 bit per enumeration)"]
256 pub states: u32,
257 #[doc = "Tables to dump (NI)"]
258 pub dbs: u32,
259}
260impl Clone for Req {
261 fn clone(&self) -> Self {
262 Self::new_from_array(*self.as_array())
263 }
264}
265#[doc = "Create zero-initialized struct"]
266impl Default for Req {
267 fn default() -> Self {
268 Self::new()
269 }
270}
271impl Req {
272 #[doc = "Create zero-initialized struct"]
273 pub fn new() -> Self {
274 Self::new_from_array([0u8; Self::len()])
275 }
276 #[doc = "Copy from contents from slice"]
277 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
278 if other.len() != Self::len() {
279 return None;
280 }
281 let mut buf = [0u8; Self::len()];
282 buf.clone_from_slice(other);
283 Some(Self::new_from_array(buf))
284 }
285 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
286 pub fn new_from_zeroed(other: &[u8]) -> Self {
287 let mut buf = [0u8; Self::len()];
288 let len = buf.len().min(other.len());
289 buf[..len].clone_from_slice(&other[..len]);
290 Self::new_from_array(buf)
291 }
292 pub fn new_from_array(buf: [u8; 60usize]) -> Self {
293 unsafe { std::mem::transmute(buf) }
294 }
295 pub fn as_slice(&self) -> &[u8] {
296 unsafe {
297 let ptr: *const u8 = std::mem::transmute(self as *const Self);
298 std::slice::from_raw_parts(ptr, Self::len())
299 }
300 }
301 pub fn from_slice(buf: &[u8]) -> &Self {
302 assert!(buf.len() >= Self::len());
303 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
304 unsafe { std::mem::transmute(buf.as_ptr()) }
305 }
306 pub fn as_array(&self) -> &[u8; 60usize] {
307 unsafe { std::mem::transmute(self) }
308 }
309 pub fn from_array(buf: &[u8; 60usize]) -> &Self {
310 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
311 unsafe { std::mem::transmute(buf) }
312 }
313 pub fn into_array(self) -> [u8; 60usize] {
314 unsafe { std::mem::transmute(self) }
315 }
316 pub const fn len() -> usize {
317 const _: () = assert!(std::mem::size_of::<Req>() == 60usize);
318 60usize
319 }
320}
321impl std::fmt::Debug for Req {
322 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
323 fmt.debug_struct("Req")
324 .field("family", &self.family)
325 .field("src_len", &self.src_len)
326 .field("dst_len", &self.dst_len)
327 .field("ext", &self.ext)
328 .field("sockid", &self.sockid)
329 .field(
330 "states",
331 &FormatFlags(self.states.into(), |val| {
332 TcpState::from_value(val.trailing_zeros().into())
333 }),
334 )
335 .field("dbs", &self.dbs)
336 .finish()
337 }
338}
339#[repr(C, packed(4))]
340pub struct ReqV2 {
341 pub family: u8,
342 pub protocol: u8,
343 pub ext: u8,
344 pub pad: u8,
345 #[doc = "Associated type: [`TcpState`] (1 bit per enumeration)"]
346 pub states: u32,
347 pub sockid: Sockid,
348}
349impl Clone for ReqV2 {
350 fn clone(&self) -> Self {
351 Self::new_from_array(*self.as_array())
352 }
353}
354#[doc = "Create zero-initialized struct"]
355impl Default for ReqV2 {
356 fn default() -> Self {
357 Self::new()
358 }
359}
360impl ReqV2 {
361 #[doc = "Create zero-initialized struct"]
362 pub fn new() -> Self {
363 Self::new_from_array([0u8; Self::len()])
364 }
365 #[doc = "Copy from contents from slice"]
366 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
367 if other.len() != Self::len() {
368 return None;
369 }
370 let mut buf = [0u8; Self::len()];
371 buf.clone_from_slice(other);
372 Some(Self::new_from_array(buf))
373 }
374 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
375 pub fn new_from_zeroed(other: &[u8]) -> Self {
376 let mut buf = [0u8; Self::len()];
377 let len = buf.len().min(other.len());
378 buf[..len].clone_from_slice(&other[..len]);
379 Self::new_from_array(buf)
380 }
381 pub fn new_from_array(buf: [u8; 56usize]) -> Self {
382 unsafe { std::mem::transmute(buf) }
383 }
384 pub fn as_slice(&self) -> &[u8] {
385 unsafe {
386 let ptr: *const u8 = std::mem::transmute(self as *const Self);
387 std::slice::from_raw_parts(ptr, Self::len())
388 }
389 }
390 pub fn from_slice(buf: &[u8]) -> &Self {
391 assert!(buf.len() >= Self::len());
392 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
393 unsafe { std::mem::transmute(buf.as_ptr()) }
394 }
395 pub fn as_array(&self) -> &[u8; 56usize] {
396 unsafe { std::mem::transmute(self) }
397 }
398 pub fn from_array(buf: &[u8; 56usize]) -> &Self {
399 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
400 unsafe { std::mem::transmute(buf) }
401 }
402 pub fn into_array(self) -> [u8; 56usize] {
403 unsafe { std::mem::transmute(self) }
404 }
405 pub const fn len() -> usize {
406 const _: () = assert!(std::mem::size_of::<ReqV2>() == 56usize);
407 56usize
408 }
409}
410impl std::fmt::Debug for ReqV2 {
411 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
412 fmt.debug_struct("ReqV2")
413 .field("family", &self.family)
414 .field("protocol", &self.protocol)
415 .field("ext", &self.ext)
416 .field("pad", &self.pad)
417 .field(
418 "states",
419 &FormatFlags(self.states.into(), |val| {
420 TcpState::from_value(val.trailing_zeros().into())
421 }),
422 )
423 .field("sockid", &self.sockid)
424 .finish()
425 }
426}
427#[repr(C, packed(4))]
428pub struct ReqRaw {
429 pub family: u8,
430 pub protocol: u8,
431 pub ext: u8,
432 pub raw_protocol: u8,
433 #[doc = "Associated type: [`TcpState`] (1 bit per enumeration)"]
434 pub states: u32,
435 pub sockid: Sockid,
436}
437impl Clone for ReqRaw {
438 fn clone(&self) -> Self {
439 Self::new_from_array(*self.as_array())
440 }
441}
442#[doc = "Create zero-initialized struct"]
443impl Default for ReqRaw {
444 fn default() -> Self {
445 Self::new()
446 }
447}
448impl ReqRaw {
449 #[doc = "Create zero-initialized struct"]
450 pub fn new() -> Self {
451 Self::new_from_array([0u8; Self::len()])
452 }
453 #[doc = "Copy from contents from slice"]
454 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
455 if other.len() != Self::len() {
456 return None;
457 }
458 let mut buf = [0u8; Self::len()];
459 buf.clone_from_slice(other);
460 Some(Self::new_from_array(buf))
461 }
462 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
463 pub fn new_from_zeroed(other: &[u8]) -> Self {
464 let mut buf = [0u8; Self::len()];
465 let len = buf.len().min(other.len());
466 buf[..len].clone_from_slice(&other[..len]);
467 Self::new_from_array(buf)
468 }
469 pub fn new_from_array(buf: [u8; 56usize]) -> Self {
470 unsafe { std::mem::transmute(buf) }
471 }
472 pub fn as_slice(&self) -> &[u8] {
473 unsafe {
474 let ptr: *const u8 = std::mem::transmute(self as *const Self);
475 std::slice::from_raw_parts(ptr, Self::len())
476 }
477 }
478 pub fn from_slice(buf: &[u8]) -> &Self {
479 assert!(buf.len() >= Self::len());
480 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
481 unsafe { std::mem::transmute(buf.as_ptr()) }
482 }
483 pub fn as_array(&self) -> &[u8; 56usize] {
484 unsafe { std::mem::transmute(self) }
485 }
486 pub fn from_array(buf: &[u8; 56usize]) -> &Self {
487 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
488 unsafe { std::mem::transmute(buf) }
489 }
490 pub fn into_array(self) -> [u8; 56usize] {
491 unsafe { std::mem::transmute(self) }
492 }
493 pub const fn len() -> usize {
494 const _: () = assert!(std::mem::size_of::<ReqRaw>() == 56usize);
495 56usize
496 }
497}
498impl std::fmt::Debug for ReqRaw {
499 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
500 fmt.debug_struct("ReqRaw")
501 .field("family", &self.family)
502 .field("protocol", &self.protocol)
503 .field("ext", &self.ext)
504 .field("raw_protocol", &self.raw_protocol)
505 .field(
506 "states",
507 &FormatFlags(self.states.into(), |val| {
508 TcpState::from_value(val.trailing_zeros().into())
509 }),
510 )
511 .field("sockid", &self.sockid)
512 .finish()
513 }
514}
515#[repr(C, packed(4))]
516pub struct Msg {
517 pub family: u8,
518 #[doc = "Associated type: [`TcpState`] (enum)"]
519 pub state: u8,
520 pub timer: u8,
521 pub retrans: u8,
522 pub sockid: Sockid,
523 pub expires: u32,
524 pub rqueue: u32,
525 pub wqueue: u32,
526 pub uid: u32,
527 pub inode: u32,
528}
529impl Clone for Msg {
530 fn clone(&self) -> Self {
531 Self::new_from_array(*self.as_array())
532 }
533}
534#[doc = "Create zero-initialized struct"]
535impl Default for Msg {
536 fn default() -> Self {
537 Self::new()
538 }
539}
540impl Msg {
541 #[doc = "Create zero-initialized struct"]
542 pub fn new() -> Self {
543 Self::new_from_array([0u8; Self::len()])
544 }
545 #[doc = "Copy from contents from slice"]
546 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
547 if other.len() != Self::len() {
548 return None;
549 }
550 let mut buf = [0u8; Self::len()];
551 buf.clone_from_slice(other);
552 Some(Self::new_from_array(buf))
553 }
554 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
555 pub fn new_from_zeroed(other: &[u8]) -> Self {
556 let mut buf = [0u8; Self::len()];
557 let len = buf.len().min(other.len());
558 buf[..len].clone_from_slice(&other[..len]);
559 Self::new_from_array(buf)
560 }
561 pub fn new_from_array(buf: [u8; 72usize]) -> Self {
562 unsafe { std::mem::transmute(buf) }
563 }
564 pub fn as_slice(&self) -> &[u8] {
565 unsafe {
566 let ptr: *const u8 = std::mem::transmute(self as *const Self);
567 std::slice::from_raw_parts(ptr, Self::len())
568 }
569 }
570 pub fn from_slice(buf: &[u8]) -> &Self {
571 assert!(buf.len() >= Self::len());
572 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
573 unsafe { std::mem::transmute(buf.as_ptr()) }
574 }
575 pub fn as_array(&self) -> &[u8; 72usize] {
576 unsafe { std::mem::transmute(self) }
577 }
578 pub fn from_array(buf: &[u8; 72usize]) -> &Self {
579 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
580 unsafe { std::mem::transmute(buf) }
581 }
582 pub fn into_array(self) -> [u8; 72usize] {
583 unsafe { std::mem::transmute(self) }
584 }
585 pub const fn len() -> usize {
586 const _: () = assert!(std::mem::size_of::<Msg>() == 72usize);
587 72usize
588 }
589}
590impl std::fmt::Debug for Msg {
591 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
592 fmt.debug_struct("Msg")
593 .field("family", &self.family)
594 .field(
595 "state",
596 &FormatEnum(self.state.into(), TcpState::from_value),
597 )
598 .field("timer", &self.timer)
599 .field("retrans", &self.retrans)
600 .field("sockid", &self.sockid)
601 .field("expires", &self.expires)
602 .field("rqueue", &self.rqueue)
603 .field("wqueue", &self.wqueue)
604 .field("uid", &self.uid)
605 .field("inode", &self.inode)
606 .finish()
607 }
608}
609#[repr(C, packed(4))]
610pub struct BytecodeOp {
611 #[doc = "Associated type: [`BytecodeOpCode`] (enum)"]
612 pub code: u8,
613 #[doc = "offset to jump on match"]
614 pub yes: u8,
615 #[doc = "offset to jump on non\\-match"]
616 pub no: u16,
617}
618impl Clone for BytecodeOp {
619 fn clone(&self) -> Self {
620 Self::new_from_array(*self.as_array())
621 }
622}
623#[doc = "Create zero-initialized struct"]
624impl Default for BytecodeOp {
625 fn default() -> Self {
626 Self::new()
627 }
628}
629impl BytecodeOp {
630 #[doc = "Create zero-initialized struct"]
631 pub fn new() -> Self {
632 Self::new_from_array([0u8; Self::len()])
633 }
634 #[doc = "Copy from contents from slice"]
635 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
636 if other.len() != Self::len() {
637 return None;
638 }
639 let mut buf = [0u8; Self::len()];
640 buf.clone_from_slice(other);
641 Some(Self::new_from_array(buf))
642 }
643 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
644 pub fn new_from_zeroed(other: &[u8]) -> Self {
645 let mut buf = [0u8; Self::len()];
646 let len = buf.len().min(other.len());
647 buf[..len].clone_from_slice(&other[..len]);
648 Self::new_from_array(buf)
649 }
650 pub fn new_from_array(buf: [u8; 4usize]) -> Self {
651 unsafe { std::mem::transmute(buf) }
652 }
653 pub fn as_slice(&self) -> &[u8] {
654 unsafe {
655 let ptr: *const u8 = std::mem::transmute(self as *const Self);
656 std::slice::from_raw_parts(ptr, Self::len())
657 }
658 }
659 pub fn from_slice(buf: &[u8]) -> &Self {
660 assert!(buf.len() >= Self::len());
661 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
662 unsafe { std::mem::transmute(buf.as_ptr()) }
663 }
664 pub fn as_array(&self) -> &[u8; 4usize] {
665 unsafe { std::mem::transmute(self) }
666 }
667 pub fn from_array(buf: &[u8; 4usize]) -> &Self {
668 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
669 unsafe { std::mem::transmute(buf) }
670 }
671 pub fn into_array(self) -> [u8; 4usize] {
672 unsafe { std::mem::transmute(self) }
673 }
674 pub const fn len() -> usize {
675 const _: () = assert!(std::mem::size_of::<BytecodeOp>() == 4usize);
676 4usize
677 }
678}
679impl std::fmt::Debug for BytecodeOp {
680 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
681 fmt.debug_struct("BytecodeOp")
682 .field(
683 "code",
684 &FormatEnum(self.code.into(), BytecodeOpCode::from_value),
685 )
686 .field("yes", &self.yes)
687 .field("no", &self.no)
688 .finish()
689 }
690}
691#[repr(C, packed(4))]
692pub struct Hostcond {
693 #[doc = "Socket address family"]
694 pub family: u8,
695 #[doc = "Number of bits to compare"]
696 pub prefix_len: u8,
697 pub _pad_2: [u8; 2usize],
698 pub port: i32,
699}
700impl Clone for Hostcond {
701 fn clone(&self) -> Self {
702 Self::new_from_array(*self.as_array())
703 }
704}
705#[doc = "Create zero-initialized struct"]
706impl Default for Hostcond {
707 fn default() -> Self {
708 Self::new()
709 }
710}
711impl Hostcond {
712 #[doc = "Create zero-initialized struct"]
713 pub fn new() -> Self {
714 Self::new_from_array([0u8; Self::len()])
715 }
716 #[doc = "Copy from contents from slice"]
717 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
718 if other.len() != Self::len() {
719 return None;
720 }
721 let mut buf = [0u8; Self::len()];
722 buf.clone_from_slice(other);
723 Some(Self::new_from_array(buf))
724 }
725 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
726 pub fn new_from_zeroed(other: &[u8]) -> Self {
727 let mut buf = [0u8; Self::len()];
728 let len = buf.len().min(other.len());
729 buf[..len].clone_from_slice(&other[..len]);
730 Self::new_from_array(buf)
731 }
732 pub fn new_from_array(buf: [u8; 8usize]) -> Self {
733 unsafe { std::mem::transmute(buf) }
734 }
735 pub fn as_slice(&self) -> &[u8] {
736 unsafe {
737 let ptr: *const u8 = std::mem::transmute(self as *const Self);
738 std::slice::from_raw_parts(ptr, Self::len())
739 }
740 }
741 pub fn from_slice(buf: &[u8]) -> &Self {
742 assert!(buf.len() >= Self::len());
743 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
744 unsafe { std::mem::transmute(buf.as_ptr()) }
745 }
746 pub fn as_array(&self) -> &[u8; 8usize] {
747 unsafe { std::mem::transmute(self) }
748 }
749 pub fn from_array(buf: &[u8; 8usize]) -> &Self {
750 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
751 unsafe { std::mem::transmute(buf) }
752 }
753 pub fn into_array(self) -> [u8; 8usize] {
754 unsafe { std::mem::transmute(self) }
755 }
756 pub const fn len() -> usize {
757 const _: () = assert!(std::mem::size_of::<Hostcond>() == 8usize);
758 8usize
759 }
760}
761impl std::fmt::Debug for Hostcond {
762 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
763 fmt.debug_struct("Hostcond")
764 .field("family", &self.family)
765 .field("prefix_len", &self.prefix_len)
766 .field("port", &self.port)
767 .finish()
768 }
769}
770#[derive(Debug)]
771#[repr(C, packed(4))]
772pub struct Markcond {
773 pub mark: u32,
774 pub mask: u32,
775}
776impl Clone for Markcond {
777 fn clone(&self) -> Self {
778 Self::new_from_array(*self.as_array())
779 }
780}
781#[doc = "Create zero-initialized struct"]
782impl Default for Markcond {
783 fn default() -> Self {
784 Self::new()
785 }
786}
787impl Markcond {
788 #[doc = "Create zero-initialized struct"]
789 pub fn new() -> Self {
790 Self::new_from_array([0u8; Self::len()])
791 }
792 #[doc = "Copy from contents from slice"]
793 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
794 if other.len() != Self::len() {
795 return None;
796 }
797 let mut buf = [0u8; Self::len()];
798 buf.clone_from_slice(other);
799 Some(Self::new_from_array(buf))
800 }
801 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
802 pub fn new_from_zeroed(other: &[u8]) -> Self {
803 let mut buf = [0u8; Self::len()];
804 let len = buf.len().min(other.len());
805 buf[..len].clone_from_slice(&other[..len]);
806 Self::new_from_array(buf)
807 }
808 pub fn new_from_array(buf: [u8; 8usize]) -> Self {
809 unsafe { std::mem::transmute(buf) }
810 }
811 pub fn as_slice(&self) -> &[u8] {
812 unsafe {
813 let ptr: *const u8 = std::mem::transmute(self as *const Self);
814 std::slice::from_raw_parts(ptr, Self::len())
815 }
816 }
817 pub fn from_slice(buf: &[u8]) -> &Self {
818 assert!(buf.len() >= Self::len());
819 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
820 unsafe { std::mem::transmute(buf.as_ptr()) }
821 }
822 pub fn as_array(&self) -> &[u8; 8usize] {
823 unsafe { std::mem::transmute(self) }
824 }
825 pub fn from_array(buf: &[u8; 8usize]) -> &Self {
826 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
827 unsafe { std::mem::transmute(buf) }
828 }
829 pub fn into_array(self) -> [u8; 8usize] {
830 unsafe { std::mem::transmute(self) }
831 }
832 pub const fn len() -> usize {
833 const _: () = assert!(std::mem::size_of::<Markcond>() == 8usize);
834 8usize
835 }
836}
837#[derive(Debug)]
838#[repr(C, packed(4))]
839pub struct Meminfo {
840 pub rmem: u32,
841 pub wmem: u32,
842 pub fmem: u32,
843 pub tmem: u32,
844}
845impl Clone for Meminfo {
846 fn clone(&self) -> Self {
847 Self::new_from_array(*self.as_array())
848 }
849}
850#[doc = "Create zero-initialized struct"]
851impl Default for Meminfo {
852 fn default() -> Self {
853 Self::new()
854 }
855}
856impl Meminfo {
857 #[doc = "Create zero-initialized struct"]
858 pub fn new() -> Self {
859 Self::new_from_array([0u8; Self::len()])
860 }
861 #[doc = "Copy from contents from slice"]
862 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
863 if other.len() != Self::len() {
864 return None;
865 }
866 let mut buf = [0u8; Self::len()];
867 buf.clone_from_slice(other);
868 Some(Self::new_from_array(buf))
869 }
870 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
871 pub fn new_from_zeroed(other: &[u8]) -> Self {
872 let mut buf = [0u8; Self::len()];
873 let len = buf.len().min(other.len());
874 buf[..len].clone_from_slice(&other[..len]);
875 Self::new_from_array(buf)
876 }
877 pub fn new_from_array(buf: [u8; 16usize]) -> Self {
878 unsafe { std::mem::transmute(buf) }
879 }
880 pub fn as_slice(&self) -> &[u8] {
881 unsafe {
882 let ptr: *const u8 = std::mem::transmute(self as *const Self);
883 std::slice::from_raw_parts(ptr, Self::len())
884 }
885 }
886 pub fn from_slice(buf: &[u8]) -> &Self {
887 assert!(buf.len() >= Self::len());
888 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
889 unsafe { std::mem::transmute(buf.as_ptr()) }
890 }
891 pub fn as_array(&self) -> &[u8; 16usize] {
892 unsafe { std::mem::transmute(self) }
893 }
894 pub fn from_array(buf: &[u8; 16usize]) -> &Self {
895 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
896 unsafe { std::mem::transmute(buf) }
897 }
898 pub fn into_array(self) -> [u8; 16usize] {
899 unsafe { std::mem::transmute(self) }
900 }
901 pub const fn len() -> usize {
902 const _: () = assert!(std::mem::size_of::<Meminfo>() == 16usize);
903 16usize
904 }
905}
906#[derive(Debug)]
907#[repr(C, packed(4))]
908pub struct TcpvegasInfo {
909 pub enabled: u32,
910 pub rttcnt: u32,
911 pub rtt: u32,
912 pub minrtt: u32,
913}
914impl Clone for TcpvegasInfo {
915 fn clone(&self) -> Self {
916 Self::new_from_array(*self.as_array())
917 }
918}
919#[doc = "Create zero-initialized struct"]
920impl Default for TcpvegasInfo {
921 fn default() -> Self {
922 Self::new()
923 }
924}
925impl TcpvegasInfo {
926 #[doc = "Create zero-initialized struct"]
927 pub fn new() -> Self {
928 Self::new_from_array([0u8; Self::len()])
929 }
930 #[doc = "Copy from contents from slice"]
931 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
932 if other.len() != Self::len() {
933 return None;
934 }
935 let mut buf = [0u8; Self::len()];
936 buf.clone_from_slice(other);
937 Some(Self::new_from_array(buf))
938 }
939 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
940 pub fn new_from_zeroed(other: &[u8]) -> Self {
941 let mut buf = [0u8; Self::len()];
942 let len = buf.len().min(other.len());
943 buf[..len].clone_from_slice(&other[..len]);
944 Self::new_from_array(buf)
945 }
946 pub fn new_from_array(buf: [u8; 16usize]) -> Self {
947 unsafe { std::mem::transmute(buf) }
948 }
949 pub fn as_slice(&self) -> &[u8] {
950 unsafe {
951 let ptr: *const u8 = std::mem::transmute(self as *const Self);
952 std::slice::from_raw_parts(ptr, Self::len())
953 }
954 }
955 pub fn from_slice(buf: &[u8]) -> &Self {
956 assert!(buf.len() >= Self::len());
957 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
958 unsafe { std::mem::transmute(buf.as_ptr()) }
959 }
960 pub fn as_array(&self) -> &[u8; 16usize] {
961 unsafe { std::mem::transmute(self) }
962 }
963 pub fn from_array(buf: &[u8; 16usize]) -> &Self {
964 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
965 unsafe { std::mem::transmute(buf) }
966 }
967 pub fn into_array(self) -> [u8; 16usize] {
968 unsafe { std::mem::transmute(self) }
969 }
970 pub const fn len() -> usize {
971 const _: () = assert!(std::mem::size_of::<TcpvegasInfo>() == 16usize);
972 16usize
973 }
974}
975#[derive(Debug)]
976#[repr(C, packed(4))]
977pub struct TcpDctcpInfo {
978 pub enabled: u16,
979 pub ce_state: u16,
980 pub alpha: u32,
981 pub ab_ecn: u32,
982 pub ab_tot: u32,
983}
984impl Clone for TcpDctcpInfo {
985 fn clone(&self) -> Self {
986 Self::new_from_array(*self.as_array())
987 }
988}
989#[doc = "Create zero-initialized struct"]
990impl Default for TcpDctcpInfo {
991 fn default() -> Self {
992 Self::new()
993 }
994}
995impl TcpDctcpInfo {
996 #[doc = "Create zero-initialized struct"]
997 pub fn new() -> Self {
998 Self::new_from_array([0u8; Self::len()])
999 }
1000 #[doc = "Copy from contents from slice"]
1001 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
1002 if other.len() != Self::len() {
1003 return None;
1004 }
1005 let mut buf = [0u8; Self::len()];
1006 buf.clone_from_slice(other);
1007 Some(Self::new_from_array(buf))
1008 }
1009 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
1010 pub fn new_from_zeroed(other: &[u8]) -> Self {
1011 let mut buf = [0u8; Self::len()];
1012 let len = buf.len().min(other.len());
1013 buf[..len].clone_from_slice(&other[..len]);
1014 Self::new_from_array(buf)
1015 }
1016 pub fn new_from_array(buf: [u8; 16usize]) -> Self {
1017 unsafe { std::mem::transmute(buf) }
1018 }
1019 pub fn as_slice(&self) -> &[u8] {
1020 unsafe {
1021 let ptr: *const u8 = std::mem::transmute(self as *const Self);
1022 std::slice::from_raw_parts(ptr, Self::len())
1023 }
1024 }
1025 pub fn from_slice(buf: &[u8]) -> &Self {
1026 assert!(buf.len() >= Self::len());
1027 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
1028 unsafe { std::mem::transmute(buf.as_ptr()) }
1029 }
1030 pub fn as_array(&self) -> &[u8; 16usize] {
1031 unsafe { std::mem::transmute(self) }
1032 }
1033 pub fn from_array(buf: &[u8; 16usize]) -> &Self {
1034 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
1035 unsafe { std::mem::transmute(buf) }
1036 }
1037 pub fn into_array(self) -> [u8; 16usize] {
1038 unsafe { std::mem::transmute(self) }
1039 }
1040 pub const fn len() -> usize {
1041 const _: () = assert!(std::mem::size_of::<TcpDctcpInfo>() == 16usize);
1042 16usize
1043 }
1044}
1045#[derive(Debug)]
1046#[repr(C, packed(4))]
1047pub struct TcpBbrInfo {
1048 #[doc = "lower 32 bits of bw"]
1049 pub bw_lo: u32,
1050 #[doc = "upper 32 bits of bw"]
1051 pub bw_hi: u32,
1052 #[doc = "min\\-filtered RTT in uSec"]
1053 pub min_rtt: u32,
1054 #[doc = "pacing gain shifted left 8 bits"]
1055 pub pacing_gain: u32,
1056 #[doc = "cwnd gain shifted left 8 bits"]
1057 pub cwnd_gain: u32,
1058}
1059impl Clone for TcpBbrInfo {
1060 fn clone(&self) -> Self {
1061 Self::new_from_array(*self.as_array())
1062 }
1063}
1064#[doc = "Create zero-initialized struct"]
1065impl Default for TcpBbrInfo {
1066 fn default() -> Self {
1067 Self::new()
1068 }
1069}
1070impl TcpBbrInfo {
1071 #[doc = "Create zero-initialized struct"]
1072 pub fn new() -> Self {
1073 Self::new_from_array([0u8; Self::len()])
1074 }
1075 #[doc = "Copy from contents from slice"]
1076 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
1077 if other.len() != Self::len() {
1078 return None;
1079 }
1080 let mut buf = [0u8; Self::len()];
1081 buf.clone_from_slice(other);
1082 Some(Self::new_from_array(buf))
1083 }
1084 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
1085 pub fn new_from_zeroed(other: &[u8]) -> Self {
1086 let mut buf = [0u8; Self::len()];
1087 let len = buf.len().min(other.len());
1088 buf[..len].clone_from_slice(&other[..len]);
1089 Self::new_from_array(buf)
1090 }
1091 pub fn new_from_array(buf: [u8; 20usize]) -> Self {
1092 unsafe { std::mem::transmute(buf) }
1093 }
1094 pub fn as_slice(&self) -> &[u8] {
1095 unsafe {
1096 let ptr: *const u8 = std::mem::transmute(self as *const Self);
1097 std::slice::from_raw_parts(ptr, Self::len())
1098 }
1099 }
1100 pub fn from_slice(buf: &[u8]) -> &Self {
1101 assert!(buf.len() >= Self::len());
1102 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
1103 unsafe { std::mem::transmute(buf.as_ptr()) }
1104 }
1105 pub fn as_array(&self) -> &[u8; 20usize] {
1106 unsafe { std::mem::transmute(self) }
1107 }
1108 pub fn from_array(buf: &[u8; 20usize]) -> &Self {
1109 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
1110 unsafe { std::mem::transmute(buf) }
1111 }
1112 pub fn into_array(self) -> [u8; 20usize] {
1113 unsafe { std::mem::transmute(self) }
1114 }
1115 pub const fn len() -> usize {
1116 const _: () = assert!(std::mem::size_of::<TcpBbrInfo>() == 20usize);
1117 20usize
1118 }
1119}
1120#[repr(C, packed(4))]
1121pub struct TcpInfo {
1122 #[doc = "TCP state\nAssociated type: [`TcpState`] (enum)"]
1123 pub state: u8,
1124 #[doc = "Congestion avoidance state"]
1125 pub ca_state: u8,
1126 #[doc = "Number of retransmits"]
1127 pub retransmits: u8,
1128 #[doc = "Number of probes"]
1129 pub probes: u8,
1130 #[doc = "Backoff count"]
1131 pub backoff: u8,
1132 #[doc = "TCP options"]
1133 pub options: u8,
1134 pub _bits_snd_wscale: u8,
1135 pub _bits_delivery_rate_app_limited: u8,
1136 #[doc = "Retransmission timeout in microseconds"]
1137 pub rto: u32,
1138 #[doc = "Delayed ACK timeout in microseconds"]
1139 pub ato: u32,
1140 #[doc = "Send maximum segment size"]
1141 pub snd_mss: u32,
1142 #[doc = "Receive maximum segment size"]
1143 pub rcv_mss: u32,
1144 #[doc = "Number of unacknowledged segments"]
1145 pub unacked: u32,
1146 #[doc = "Number of SACKed segments"]
1147 pub sacked: u32,
1148 #[doc = "Number of lost segments"]
1149 pub lost: u32,
1150 #[doc = "Number of retransmitted segments"]
1151 pub retrans: u32,
1152 #[doc = "Forward Acknowledgment count"]
1153 pub fackets: u32,
1154 #[doc = "Time since last data sent (jiffies)"]
1155 pub last_data_sent: u32,
1156 #[doc = "Time since last ACK sent (jiffies, Not remembered, sorry\\.)"]
1157 pub last_ack_sent: u32,
1158 #[doc = "Time since last data received (jiffies)"]
1159 pub last_data_recv: u32,
1160 #[doc = "Time since last ACK received (jiffies)"]
1161 pub last_ack_recv: u32,
1162 #[doc = "Path MTU"]
1163 pub pmtu: u32,
1164 #[doc = "Receive slow start threshold"]
1165 pub rcv_ssthresh: u32,
1166 #[doc = "Smoothed round trip time in microseconds"]
1167 pub rtt: u32,
1168 #[doc = "Round trip time variation"]
1169 pub rttvar: u32,
1170 #[doc = "Send slow start threshold"]
1171 pub snd_ssthresh: u32,
1172 #[doc = "Send congestion window"]
1173 pub snd_cwnd: u32,
1174 #[doc = "Advertised MSS"]
1175 pub advmss: u32,
1176 #[doc = "Reordering threshold"]
1177 pub reordering: u32,
1178 #[doc = "Receiver side RTT"]
1179 pub rcv_rtt: u32,
1180 #[doc = "Receiver space"]
1181 pub rcv_space: u32,
1182 #[doc = "Total number of retransmitted segments"]
1183 pub total_retrans: u32,
1184 #[doc = "Pacing rate in bytes per second"]
1185 pub pacing_rate: u64,
1186 #[doc = "Maximum pacing rate in bytes per second"]
1187 pub max_pacing_rate: u64,
1188 #[doc = "RFC4898 tcpEStatsAppHCThruOctetsAcked"]
1189 pub bytes_acked: u64,
1190 #[doc = "RFC4898 tcpEStatsAppHCThruOctetsReceived"]
1191 pub bytes_received: u64,
1192 #[doc = "RFC4898 tcpEStatsPerfSegsOut"]
1193 pub segs_out: u32,
1194 #[doc = "RFC4898 tcpEStatsPerfSegsIn"]
1195 pub segs_in: u32,
1196 #[doc = "Bytes in write queue not yet sent"]
1197 pub notsent_bytes: u32,
1198 #[doc = "Minimum RTT observed in microseconds"]
1199 pub min_rtt: u32,
1200 #[doc = "RFC4898 tcpEStatsDataSegsIn"]
1201 pub data_segs_in: u32,
1202 #[doc = "RFC4898 tcpEStatsDataSegsOut"]
1203 pub data_segs_out: u32,
1204 #[doc = "Delivery rate in bytes per second"]
1205 pub delivery_rate: u64,
1206 #[doc = "Time (usec) busy sending data"]
1207 pub busy_time: u64,
1208 #[doc = "Time (usec) limited by receive window"]
1209 pub rwnd_limited: u64,
1210 #[doc = "Time (usec) limited by send buffer"]
1211 pub sndbuf_limited: u64,
1212 #[doc = "Packets delivered"]
1213 pub delivered: u32,
1214 #[doc = "Packets delivered with CE marks"]
1215 pub delivered_ce: u32,
1216 #[doc = "RFC4898 tcpEStatsPerfHCDataOctetsOut"]
1217 pub bytes_sent: u64,
1218 #[doc = "RFC4898 tcpEStatsPerfOctetsRetrans"]
1219 pub bytes_retrans: u64,
1220 #[doc = "RFC4898 tcpEStatsStackDSACKDups"]
1221 pub dsack_dups: u32,
1222 #[doc = "Reordering events seen"]
1223 pub reord_seen: u32,
1224 #[doc = "Out\\-of\\-order packets received"]
1225 pub rcv_ooopack: u32,
1226 #[doc = "Peer's advertised receive window after scaling (bytes)"]
1227 pub snd_wnd: u32,
1228 #[doc = "Local advertised receive window after scaling (bytes)"]
1229 pub rcv_wnd: u32,
1230 #[doc = "PLB or timeout triggered rehash attempts"]
1231 pub rehash: u32,
1232 #[doc = "Total number of RTO timeouts, including SYN/SYN\\-ACK and recurring timeouts"]
1233 pub total_rto: u16,
1234 #[doc = "Total number of RTO recoveries, including any unfinished recovery"]
1235 pub total_rto_recoveries: u16,
1236 #[doc = "Total time spent in RTO recoveries in milliseconds, including any unfinished recovery"]
1237 pub total_rto_time: u32,
1238 #[doc = "Number of CE marks received"]
1239 pub received_ce: u32,
1240 #[doc = "Accurate ECN byte counters for ECT(1)"]
1241 pub delivered_e1_bytes: u32,
1242 #[doc = "Accurate ECN byte counters for ECT(0)"]
1243 pub delivered_e0_bytes: u32,
1244 #[doc = "Accurate ECN byte counters for CE"]
1245 pub delivered_ce_bytes: u32,
1246 #[doc = "Received bytes with ECT(1) marks"]
1247 pub received_e1_bytes: u32,
1248 #[doc = "Received bytes with ECT(0) marks"]
1249 pub received_e0_bytes: u32,
1250 #[doc = "Received bytes with CE marks"]
1251 pub received_ce_bytes: u32,
1252 #[doc = "ACK ECN failure mode"]
1253 pub accecn_fail_mode: u16,
1254 #[doc = "ACK ECN option seen"]
1255 pub accecn_opt_seen: u16,
1256}
1257impl Clone for TcpInfo {
1258 fn clone(&self) -> Self {
1259 Self::new_from_array(*self.as_array())
1260 }
1261}
1262#[doc = "Create zero-initialized struct"]
1263impl Default for TcpInfo {
1264 fn default() -> Self {
1265 Self::new()
1266 }
1267}
1268impl TcpInfo {
1269 #[doc = "Create zero-initialized struct"]
1270 pub fn new() -> Self {
1271 Self::new_from_array([0u8; Self::len()])
1272 }
1273 #[doc = "Copy from contents from slice"]
1274 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
1275 if other.len() != Self::len() {
1276 return None;
1277 }
1278 let mut buf = [0u8; Self::len()];
1279 buf.clone_from_slice(other);
1280 Some(Self::new_from_array(buf))
1281 }
1282 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
1283 pub fn new_from_zeroed(other: &[u8]) -> Self {
1284 let mut buf = [0u8; Self::len()];
1285 let len = buf.len().min(other.len());
1286 buf[..len].clone_from_slice(&other[..len]);
1287 Self::new_from_array(buf)
1288 }
1289 pub fn new_from_array(buf: [u8; 280usize]) -> Self {
1290 unsafe { std::mem::transmute(buf) }
1291 }
1292 pub fn as_slice(&self) -> &[u8] {
1293 unsafe {
1294 let ptr: *const u8 = std::mem::transmute(self as *const Self);
1295 std::slice::from_raw_parts(ptr, Self::len())
1296 }
1297 }
1298 pub fn from_slice(buf: &[u8]) -> &Self {
1299 assert!(buf.len() >= Self::len());
1300 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
1301 unsafe { std::mem::transmute(buf.as_ptr()) }
1302 }
1303 pub fn as_array(&self) -> &[u8; 280usize] {
1304 unsafe { std::mem::transmute(self) }
1305 }
1306 pub fn from_array(buf: &[u8; 280usize]) -> &Self {
1307 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
1308 unsafe { std::mem::transmute(buf) }
1309 }
1310 pub fn into_array(self) -> [u8; 280usize] {
1311 unsafe { std::mem::transmute(self) }
1312 }
1313 pub const fn len() -> usize {
1314 const _: () = assert!(std::mem::size_of::<TcpInfo>() == 280usize);
1315 280usize
1316 }
1317 #[doc = "Send window scale"]
1318 pub fn snd_wscale(&self) -> u8 {
1319 (((self._bits_snd_wscale as u32) << 28u32) >> 28u32) as u8
1320 }
1321 #[doc = "Send window scale"]
1322 pub fn set_snd_wscale(&mut self, value: u8) {
1323 let mask = (1 << 4usize) - 1;
1324 self._bits_snd_wscale =
1325 (self._bits_snd_wscale & (!(mask << 0usize))) | ((value & mask) << 0usize);
1326 }
1327 #[doc = "Receive window scale"]
1328 pub fn rcv_wscale(&self) -> u8 {
1329 (((self._bits_snd_wscale as u32) << 24u32) >> 28u32) as u8
1330 }
1331 #[doc = "Receive window scale"]
1332 pub fn set_rcv_wscale(&mut self, value: u8) {
1333 let mask = (1 << 4usize) - 1;
1334 self._bits_snd_wscale =
1335 (self._bits_snd_wscale & (!(mask << 4usize))) | ((value & mask) << 4usize);
1336 }
1337 #[doc = "Delivery rate application limited flag"]
1338 pub fn delivery_rate_app_limited(&self) -> u8 {
1339 (((self._bits_delivery_rate_app_limited as u32) << 31u32) >> 31u32) as u8
1340 }
1341 #[doc = "Delivery rate application limited flag"]
1342 pub fn set_delivery_rate_app_limited(&mut self, value: u8) {
1343 let mask = (1 << 1usize) - 1;
1344 self._bits_delivery_rate_app_limited = (self._bits_delivery_rate_app_limited
1345 & (!(mask << 0usize)))
1346 | ((value & mask) << 0usize);
1347 }
1348 #[doc = "FastOpen client failure code"]
1349 pub fn fastopen_client_fail(&self) -> u8 {
1350 (((self._bits_delivery_rate_app_limited as u32) << 29u32) >> 30u32) as u8
1351 }
1352 #[doc = "FastOpen client failure code"]
1353 pub fn set_fastopen_client_fail(&mut self, value: u8) {
1354 let mask = (1 << 2usize) - 1;
1355 self._bits_delivery_rate_app_limited = (self._bits_delivery_rate_app_limited
1356 & (!(mask << 1usize)))
1357 | ((value & mask) << 1usize);
1358 }
1359}
1360impl std::fmt::Debug for TcpInfo {
1361 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1362 fmt.debug_struct("TcpInfo")
1363 .field(
1364 "state",
1365 &FormatEnum(self.state.into(), TcpState::from_value),
1366 )
1367 .field("ca_state", &self.ca_state)
1368 .field("retransmits", &self.retransmits)
1369 .field("probes", &self.probes)
1370 .field("backoff", &self.backoff)
1371 .field("options", &self.options)
1372 .field("snd_wscale", &self.snd_wscale())
1373 .field("rcv_wscale", &self.rcv_wscale())
1374 .field(
1375 "delivery_rate_app_limited",
1376 &self.delivery_rate_app_limited(),
1377 )
1378 .field("fastopen_client_fail", &self.fastopen_client_fail())
1379 .field("rto", &self.rto)
1380 .field("ato", &self.ato)
1381 .field("snd_mss", &self.snd_mss)
1382 .field("rcv_mss", &self.rcv_mss)
1383 .field("unacked", &self.unacked)
1384 .field("sacked", &self.sacked)
1385 .field("lost", &self.lost)
1386 .field("retrans", &self.retrans)
1387 .field("fackets", &self.fackets)
1388 .field("last_data_sent", &self.last_data_sent)
1389 .field("last_ack_sent", &self.last_ack_sent)
1390 .field("last_data_recv", &self.last_data_recv)
1391 .field("last_ack_recv", &self.last_ack_recv)
1392 .field("pmtu", &self.pmtu)
1393 .field("rcv_ssthresh", &self.rcv_ssthresh)
1394 .field("rtt", &self.rtt)
1395 .field("rttvar", &self.rttvar)
1396 .field("snd_ssthresh", &self.snd_ssthresh)
1397 .field("snd_cwnd", &self.snd_cwnd)
1398 .field("advmss", &self.advmss)
1399 .field("reordering", &self.reordering)
1400 .field("rcv_rtt", &self.rcv_rtt)
1401 .field("rcv_space", &self.rcv_space)
1402 .field("total_retrans", &self.total_retrans)
1403 .field("pacing_rate", &{ self.pacing_rate })
1404 .field("max_pacing_rate", &{ self.max_pacing_rate })
1405 .field("bytes_acked", &{ self.bytes_acked })
1406 .field("bytes_received", &{ self.bytes_received })
1407 .field("segs_out", &self.segs_out)
1408 .field("segs_in", &self.segs_in)
1409 .field("notsent_bytes", &self.notsent_bytes)
1410 .field("min_rtt", &self.min_rtt)
1411 .field("data_segs_in", &self.data_segs_in)
1412 .field("data_segs_out", &self.data_segs_out)
1413 .field("delivery_rate", &{ self.delivery_rate })
1414 .field("busy_time", &{ self.busy_time })
1415 .field("rwnd_limited", &{ self.rwnd_limited })
1416 .field("sndbuf_limited", &{ self.sndbuf_limited })
1417 .field("delivered", &self.delivered)
1418 .field("delivered_ce", &self.delivered_ce)
1419 .field("bytes_sent", &{ self.bytes_sent })
1420 .field("bytes_retrans", &{ self.bytes_retrans })
1421 .field("dsack_dups", &self.dsack_dups)
1422 .field("reord_seen", &self.reord_seen)
1423 .field("rcv_ooopack", &self.rcv_ooopack)
1424 .field("snd_wnd", &self.snd_wnd)
1425 .field("rcv_wnd", &self.rcv_wnd)
1426 .field("rehash", &self.rehash)
1427 .field("total_rto", &self.total_rto)
1428 .field("total_rto_recoveries", &self.total_rto_recoveries)
1429 .field("total_rto_time", &self.total_rto_time)
1430 .field("received_ce", &self.received_ce)
1431 .field("delivered_e1_bytes", &self.delivered_e1_bytes)
1432 .field("delivered_e0_bytes", &self.delivered_e0_bytes)
1433 .field("delivered_ce_bytes", &self.delivered_ce_bytes)
1434 .field("received_e1_bytes", &self.received_e1_bytes)
1435 .field("received_e0_bytes", &self.received_e0_bytes)
1436 .field("received_ce_bytes", &self.received_ce_bytes)
1437 .field("accecn_fail_mode", &self.accecn_fail_mode)
1438 .field("accecn_opt_seen", &self.accecn_opt_seen)
1439 .finish()
1440 }
1441}
1442#[derive(Clone)]
1443pub enum UlpInfoAttrs<'a> {
1444 #[doc = "ULP name (e\\.g\\., \"tls\", \"mptcp\")"]
1445 Name(&'a CStr),
1446 #[doc = "TLS\\-specific information"]
1447 Tls(&'a [u8]),
1448 #[doc = "MPTCP\\-specific information"]
1449 Mptcp(&'a [u8]),
1450}
1451impl<'a> IterableUlpInfoAttrs<'a> {
1452 #[doc = "ULP name (e\\.g\\., \"tls\", \"mptcp\")"]
1453 pub fn get_name(&self) -> Result<&'a CStr, ErrorContext> {
1454 let mut iter = self.clone();
1455 iter.pos = 0;
1456 for attr in iter {
1457 if let UlpInfoAttrs::Name(val) = attr? {
1458 return Ok(val);
1459 }
1460 }
1461 Err(ErrorContext::new_missing(
1462 "UlpInfoAttrs",
1463 "Name",
1464 self.orig_loc,
1465 self.buf.as_ptr() as usize,
1466 ))
1467 }
1468 #[doc = "TLS\\-specific information"]
1469 pub fn get_tls(&self) -> Result<&'a [u8], ErrorContext> {
1470 let mut iter = self.clone();
1471 iter.pos = 0;
1472 for attr in iter {
1473 if let UlpInfoAttrs::Tls(val) = attr? {
1474 return Ok(val);
1475 }
1476 }
1477 Err(ErrorContext::new_missing(
1478 "UlpInfoAttrs",
1479 "Tls",
1480 self.orig_loc,
1481 self.buf.as_ptr() as usize,
1482 ))
1483 }
1484 #[doc = "MPTCP\\-specific information"]
1485 pub fn get_mptcp(&self) -> Result<&'a [u8], ErrorContext> {
1486 let mut iter = self.clone();
1487 iter.pos = 0;
1488 for attr in iter {
1489 if let UlpInfoAttrs::Mptcp(val) = attr? {
1490 return Ok(val);
1491 }
1492 }
1493 Err(ErrorContext::new_missing(
1494 "UlpInfoAttrs",
1495 "Mptcp",
1496 self.orig_loc,
1497 self.buf.as_ptr() as usize,
1498 ))
1499 }
1500}
1501impl UlpInfoAttrs<'_> {
1502 pub fn new<'a>(buf: &'a [u8]) -> IterableUlpInfoAttrs<'a> {
1503 IterableUlpInfoAttrs::with_loc(buf, buf.as_ptr() as usize)
1504 }
1505 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1506 let res = match r#type {
1507 1u16 => "Name",
1508 2u16 => "Tls",
1509 3u16 => "Mptcp",
1510 _ => return None,
1511 };
1512 Some(res)
1513 }
1514}
1515#[derive(Clone, Copy, Default)]
1516pub struct IterableUlpInfoAttrs<'a> {
1517 buf: &'a [u8],
1518 pos: usize,
1519 orig_loc: usize,
1520}
1521impl<'a> IterableUlpInfoAttrs<'a> {
1522 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1523 Self {
1524 buf,
1525 pos: 0,
1526 orig_loc,
1527 }
1528 }
1529 pub fn get_buf(&self) -> &'a [u8] {
1530 self.buf
1531 }
1532}
1533impl<'a> Iterator for IterableUlpInfoAttrs<'a> {
1534 type Item = Result<UlpInfoAttrs<'a>, ErrorContext>;
1535 fn next(&mut self) -> Option<Self::Item> {
1536 let pos = self.pos;
1537 let mut r#type;
1538 loop {
1539 r#type = None;
1540 if self.buf.len() == self.pos {
1541 return None;
1542 }
1543 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1544 break;
1545 };
1546 r#type = Some(header.r#type);
1547 let res = match header.r#type {
1548 1u16 => UlpInfoAttrs::Name({
1549 let res = CStr::from_bytes_with_nul(next).ok();
1550 let Some(val) = res else { break };
1551 val
1552 }),
1553 2u16 => UlpInfoAttrs::Tls({
1554 let res = Some(next);
1555 let Some(val) = res else { break };
1556 val
1557 }),
1558 3u16 => UlpInfoAttrs::Mptcp({
1559 let res = Some(next);
1560 let Some(val) = res else { break };
1561 val
1562 }),
1563 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1564 n => continue,
1565 };
1566 return Some(Ok(res));
1567 }
1568 Some(Err(ErrorContext::new(
1569 "UlpInfoAttrs",
1570 r#type.and_then(|t| UlpInfoAttrs::attr_from_type(t)),
1571 self.orig_loc,
1572 self.buf.as_ptr().wrapping_add(pos) as usize,
1573 )))
1574 }
1575}
1576impl<'a> std::fmt::Debug for IterableUlpInfoAttrs<'_> {
1577 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1578 let mut fmt = f.debug_struct("UlpInfoAttrs");
1579 for attr in self.clone() {
1580 let attr = match attr {
1581 Ok(a) => a,
1582 Err(err) => {
1583 fmt.finish()?;
1584 f.write_str("Err(")?;
1585 err.fmt(f)?;
1586 return f.write_str(")");
1587 }
1588 };
1589 match attr {
1590 UlpInfoAttrs::Name(val) => fmt.field("Name", &val),
1591 UlpInfoAttrs::Tls(val) => fmt.field("Tls", &val),
1592 UlpInfoAttrs::Mptcp(val) => fmt.field("Mptcp", &val),
1593 };
1594 }
1595 fmt.finish()
1596 }
1597}
1598impl IterableUlpInfoAttrs<'_> {
1599 pub fn lookup_attr(
1600 &self,
1601 offset: usize,
1602 missing_type: Option<u16>,
1603 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1604 let mut stack = Vec::new();
1605 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1606 if missing_type.is_some() && cur == offset {
1607 stack.push(("UlpInfoAttrs", offset));
1608 return (
1609 stack,
1610 missing_type.and_then(|t| UlpInfoAttrs::attr_from_type(t)),
1611 );
1612 }
1613 if cur > offset || cur + self.buf.len() < offset {
1614 return (stack, None);
1615 }
1616 let mut attrs = self.clone();
1617 let mut last_off = cur + attrs.pos;
1618 while let Some(attr) = attrs.next() {
1619 let Ok(attr) = attr else { break };
1620 match attr {
1621 UlpInfoAttrs::Name(val) => {
1622 if last_off == offset {
1623 stack.push(("Name", last_off));
1624 break;
1625 }
1626 }
1627 UlpInfoAttrs::Tls(val) => {
1628 if last_off == offset {
1629 stack.push(("Tls", last_off));
1630 break;
1631 }
1632 }
1633 UlpInfoAttrs::Mptcp(val) => {
1634 if last_off == offset {
1635 stack.push(("Mptcp", last_off));
1636 break;
1637 }
1638 }
1639 _ => {}
1640 };
1641 last_off = cur + attrs.pos;
1642 }
1643 if !stack.is_empty() {
1644 stack.push(("UlpInfoAttrs", cur));
1645 }
1646 (stack, None)
1647 }
1648}
1649#[derive(Clone)]
1650pub enum RequestAttrs<'a> {
1651 #[doc = "See bytecode\\-op"]
1652 Bytecode(&'a [u8]),
1653 BpfStorages(IterableBpfStorageReq<'a>),
1654 Protocol(u32),
1655}
1656impl<'a> IterableRequestAttrs<'a> {
1657 #[doc = "See bytecode\\-op"]
1658 pub fn get_bytecode(&self) -> Result<&'a [u8], ErrorContext> {
1659 let mut iter = self.clone();
1660 iter.pos = 0;
1661 for attr in iter {
1662 if let RequestAttrs::Bytecode(val) = attr? {
1663 return Ok(val);
1664 }
1665 }
1666 Err(ErrorContext::new_missing(
1667 "RequestAttrs",
1668 "Bytecode",
1669 self.orig_loc,
1670 self.buf.as_ptr() as usize,
1671 ))
1672 }
1673 pub fn get_bpf_storages(&self) -> Result<IterableBpfStorageReq<'a>, ErrorContext> {
1674 let mut iter = self.clone();
1675 iter.pos = 0;
1676 for attr in iter {
1677 if let RequestAttrs::BpfStorages(val) = attr? {
1678 return Ok(val);
1679 }
1680 }
1681 Err(ErrorContext::new_missing(
1682 "RequestAttrs",
1683 "BpfStorages",
1684 self.orig_loc,
1685 self.buf.as_ptr() as usize,
1686 ))
1687 }
1688 pub fn get_protocol(&self) -> Result<u32, ErrorContext> {
1689 let mut iter = self.clone();
1690 iter.pos = 0;
1691 for attr in iter {
1692 if let RequestAttrs::Protocol(val) = attr? {
1693 return Ok(val);
1694 }
1695 }
1696 Err(ErrorContext::new_missing(
1697 "RequestAttrs",
1698 "Protocol",
1699 self.orig_loc,
1700 self.buf.as_ptr() as usize,
1701 ))
1702 }
1703}
1704impl RequestAttrs<'_> {
1705 pub fn new<'a>(buf: &'a [u8]) -> IterableRequestAttrs<'a> {
1706 IterableRequestAttrs::with_loc(buf, buf.as_ptr() as usize)
1707 }
1708 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1709 let res = match r#type {
1710 1u16 => "Bytecode",
1711 2u16 => "BpfStorages",
1712 3u16 => "Protocol",
1713 _ => return None,
1714 };
1715 Some(res)
1716 }
1717}
1718#[derive(Clone, Copy, Default)]
1719pub struct IterableRequestAttrs<'a> {
1720 buf: &'a [u8],
1721 pos: usize,
1722 orig_loc: usize,
1723}
1724impl<'a> IterableRequestAttrs<'a> {
1725 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1726 Self {
1727 buf,
1728 pos: 0,
1729 orig_loc,
1730 }
1731 }
1732 pub fn get_buf(&self) -> &'a [u8] {
1733 self.buf
1734 }
1735}
1736impl<'a> Iterator for IterableRequestAttrs<'a> {
1737 type Item = Result<RequestAttrs<'a>, ErrorContext>;
1738 fn next(&mut self) -> Option<Self::Item> {
1739 let pos = self.pos;
1740 let mut r#type;
1741 loop {
1742 r#type = None;
1743 if self.buf.len() == self.pos {
1744 return None;
1745 }
1746 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1747 break;
1748 };
1749 r#type = Some(header.r#type);
1750 let res = match header.r#type {
1751 1u16 => RequestAttrs::Bytecode({
1752 let res = Some(next);
1753 let Some(val) = res else { break };
1754 val
1755 }),
1756 2u16 => RequestAttrs::BpfStorages({
1757 let res = Some(IterableBpfStorageReq::with_loc(next, self.orig_loc));
1758 let Some(val) = res else { break };
1759 val
1760 }),
1761 3u16 => RequestAttrs::Protocol({
1762 let res = parse_u32(next);
1763 let Some(val) = res else { break };
1764 val
1765 }),
1766 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1767 n => continue,
1768 };
1769 return Some(Ok(res));
1770 }
1771 Some(Err(ErrorContext::new(
1772 "RequestAttrs",
1773 r#type.and_then(|t| RequestAttrs::attr_from_type(t)),
1774 self.orig_loc,
1775 self.buf.as_ptr().wrapping_add(pos) as usize,
1776 )))
1777 }
1778}
1779impl<'a> std::fmt::Debug for IterableRequestAttrs<'_> {
1780 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1781 let mut fmt = f.debug_struct("RequestAttrs");
1782 for attr in self.clone() {
1783 let attr = match attr {
1784 Ok(a) => a,
1785 Err(err) => {
1786 fmt.finish()?;
1787 f.write_str("Err(")?;
1788 err.fmt(f)?;
1789 return f.write_str(")");
1790 }
1791 };
1792 match attr {
1793 RequestAttrs::Bytecode(val) => {
1794 let iter = val
1795 .chunks(BytecodeOp::len())
1796 .map(|b| BytecodeOp::new_from_zeroed(b));
1797 fmt.field("Bytecode", &FormatIter(iter))
1798 }
1799 RequestAttrs::BpfStorages(val) => fmt.field("BpfStorages", &val),
1800 RequestAttrs::Protocol(val) => fmt.field("Protocol", &val),
1801 };
1802 }
1803 fmt.finish()
1804 }
1805}
1806impl IterableRequestAttrs<'_> {
1807 pub fn lookup_attr(
1808 &self,
1809 offset: usize,
1810 missing_type: Option<u16>,
1811 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1812 let mut stack = Vec::new();
1813 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1814 if missing_type.is_some() && cur == offset {
1815 stack.push(("RequestAttrs", offset));
1816 return (
1817 stack,
1818 missing_type.and_then(|t| RequestAttrs::attr_from_type(t)),
1819 );
1820 }
1821 if cur > offset || cur + self.buf.len() < offset {
1822 return (stack, None);
1823 }
1824 let mut attrs = self.clone();
1825 let mut last_off = cur + attrs.pos;
1826 let mut missing = None;
1827 while let Some(attr) = attrs.next() {
1828 let Ok(attr) = attr else { break };
1829 match attr {
1830 RequestAttrs::Bytecode(val) => {
1831 if last_off == offset {
1832 stack.push(("Bytecode", last_off));
1833 break;
1834 }
1835 }
1836 RequestAttrs::BpfStorages(val) => {
1837 (stack, missing) = val.lookup_attr(offset, missing_type);
1838 if !stack.is_empty() {
1839 break;
1840 }
1841 }
1842 RequestAttrs::Protocol(val) => {
1843 if last_off == offset {
1844 stack.push(("Protocol", last_off));
1845 break;
1846 }
1847 }
1848 _ => {}
1849 };
1850 last_off = cur + attrs.pos;
1851 }
1852 if !stack.is_empty() {
1853 stack.push(("RequestAttrs", cur));
1854 }
1855 (stack, missing)
1856 }
1857}
1858#[derive(Clone)]
1859pub enum ReplyAttrs<'a> {
1860 #[doc = "Memory information extension"]
1861 Meminfo(Meminfo),
1862 TcpInfo(TcpInfo),
1863 #[doc = "TCP Vegas information"]
1864 Vegasinfo(TcpvegasInfo),
1865 #[doc = "Congestion control algorithm name"]
1866 Cong(&'a CStr),
1867 #[doc = "Type of Service"]
1868 Tos(u8),
1869 #[doc = "Traffic Class"]
1870 Tclass(u8),
1871 #[doc = "Socket memory information"]
1872 Skmeminfo(&'a [u8]),
1873 #[doc = "Shutdown state"]
1874 Shutdown(u8),
1875 #[doc = "TCP DCTCP information (request as INET\\_DIAG\\_VEGASINFO)"]
1876 Dctcpinfo(TcpDctcpInfo),
1877 #[doc = "Raw socket protocol (response attribute only)"]
1878 Protocol(u8),
1879 #[doc = "IPv6\\-only socket flag"]
1880 Skv6only(()),
1881 #[doc = "Local addresses\\. SCTP thing\\."]
1882 Locals(&'a [u8]),
1883 #[doc = "Peer addresses\\. SCTP thing\\."]
1884 Peers(&'a [u8]),
1885 Pad(&'a [u8]),
1886 #[doc = "Socket mark (only with CAP\\_NET\\_ADMIN)"]
1887 Mark(u32),
1888 #[doc = "TCP BBR information (request as INET\\_DIAG\\_VEGASINFO)"]
1889 Bbritfo(TcpBbrInfo),
1890 #[doc = "Class ID (request as INET\\_DIAG\\_TCLASS)"]
1891 ClassId(u32),
1892 #[doc = "MD5 signature information"]
1893 Md5sig(&'a [u8]),
1894 #[doc = "Upper Layer Protocol information"]
1895 UlpInfo(IterableUlpInfoAttrs<'a>),
1896 #[doc = "BPF storage information\nAttribute may repeat multiple times (treat it as array)"]
1897 SkBpfStorages(IterableBpfStorageReply<'a>),
1898 #[doc = "Cgroup ID"]
1899 CgroupId(u64),
1900 #[doc = "Socket options\nAssociated type: [`SockoptFlag`] (enum)"]
1901 SockoptFlags(u16),
1902}
1903impl<'a> IterableReplyAttrs<'a> {
1904 #[doc = "Memory information extension"]
1905 pub fn get_meminfo(&self) -> Result<Meminfo, ErrorContext> {
1906 let mut iter = self.clone();
1907 iter.pos = 0;
1908 for attr in iter {
1909 if let ReplyAttrs::Meminfo(val) = attr? {
1910 return Ok(val);
1911 }
1912 }
1913 Err(ErrorContext::new_missing(
1914 "ReplyAttrs",
1915 "Meminfo",
1916 self.orig_loc,
1917 self.buf.as_ptr() as usize,
1918 ))
1919 }
1920 pub fn get_tcp_info(&self) -> Result<TcpInfo, ErrorContext> {
1921 let mut iter = self.clone();
1922 iter.pos = 0;
1923 for attr in iter {
1924 if let ReplyAttrs::TcpInfo(val) = attr? {
1925 return Ok(val);
1926 }
1927 }
1928 Err(ErrorContext::new_missing(
1929 "ReplyAttrs",
1930 "TcpInfo",
1931 self.orig_loc,
1932 self.buf.as_ptr() as usize,
1933 ))
1934 }
1935 #[doc = "TCP Vegas information"]
1936 pub fn get_vegasinfo(&self) -> Result<TcpvegasInfo, ErrorContext> {
1937 let mut iter = self.clone();
1938 iter.pos = 0;
1939 for attr in iter {
1940 if let ReplyAttrs::Vegasinfo(val) = attr? {
1941 return Ok(val);
1942 }
1943 }
1944 Err(ErrorContext::new_missing(
1945 "ReplyAttrs",
1946 "Vegasinfo",
1947 self.orig_loc,
1948 self.buf.as_ptr() as usize,
1949 ))
1950 }
1951 #[doc = "Congestion control algorithm name"]
1952 pub fn get_cong(&self) -> Result<&'a CStr, ErrorContext> {
1953 let mut iter = self.clone();
1954 iter.pos = 0;
1955 for attr in iter {
1956 if let ReplyAttrs::Cong(val) = attr? {
1957 return Ok(val);
1958 }
1959 }
1960 Err(ErrorContext::new_missing(
1961 "ReplyAttrs",
1962 "Cong",
1963 self.orig_loc,
1964 self.buf.as_ptr() as usize,
1965 ))
1966 }
1967 #[doc = "Type of Service"]
1968 pub fn get_tos(&self) -> Result<u8, ErrorContext> {
1969 let mut iter = self.clone();
1970 iter.pos = 0;
1971 for attr in iter {
1972 if let ReplyAttrs::Tos(val) = attr? {
1973 return Ok(val);
1974 }
1975 }
1976 Err(ErrorContext::new_missing(
1977 "ReplyAttrs",
1978 "Tos",
1979 self.orig_loc,
1980 self.buf.as_ptr() as usize,
1981 ))
1982 }
1983 #[doc = "Traffic Class"]
1984 pub fn get_tclass(&self) -> Result<u8, ErrorContext> {
1985 let mut iter = self.clone();
1986 iter.pos = 0;
1987 for attr in iter {
1988 if let ReplyAttrs::Tclass(val) = attr? {
1989 return Ok(val);
1990 }
1991 }
1992 Err(ErrorContext::new_missing(
1993 "ReplyAttrs",
1994 "Tclass",
1995 self.orig_loc,
1996 self.buf.as_ptr() as usize,
1997 ))
1998 }
1999 #[doc = "Socket memory information"]
2000 pub fn get_skmeminfo(&self) -> Result<&'a [u8], ErrorContext> {
2001 let mut iter = self.clone();
2002 iter.pos = 0;
2003 for attr in iter {
2004 if let ReplyAttrs::Skmeminfo(val) = attr? {
2005 return Ok(val);
2006 }
2007 }
2008 Err(ErrorContext::new_missing(
2009 "ReplyAttrs",
2010 "Skmeminfo",
2011 self.orig_loc,
2012 self.buf.as_ptr() as usize,
2013 ))
2014 }
2015 #[doc = "Shutdown state"]
2016 pub fn get_shutdown(&self) -> Result<u8, ErrorContext> {
2017 let mut iter = self.clone();
2018 iter.pos = 0;
2019 for attr in iter {
2020 if let ReplyAttrs::Shutdown(val) = attr? {
2021 return Ok(val);
2022 }
2023 }
2024 Err(ErrorContext::new_missing(
2025 "ReplyAttrs",
2026 "Shutdown",
2027 self.orig_loc,
2028 self.buf.as_ptr() as usize,
2029 ))
2030 }
2031 #[doc = "TCP DCTCP information (request as INET\\_DIAG\\_VEGASINFO)"]
2032 pub fn get_dctcpinfo(&self) -> Result<TcpDctcpInfo, ErrorContext> {
2033 let mut iter = self.clone();
2034 iter.pos = 0;
2035 for attr in iter {
2036 if let ReplyAttrs::Dctcpinfo(val) = attr? {
2037 return Ok(val);
2038 }
2039 }
2040 Err(ErrorContext::new_missing(
2041 "ReplyAttrs",
2042 "Dctcpinfo",
2043 self.orig_loc,
2044 self.buf.as_ptr() as usize,
2045 ))
2046 }
2047 #[doc = "Raw socket protocol (response attribute only)"]
2048 pub fn get_protocol(&self) -> Result<u8, ErrorContext> {
2049 let mut iter = self.clone();
2050 iter.pos = 0;
2051 for attr in iter {
2052 if let ReplyAttrs::Protocol(val) = attr? {
2053 return Ok(val);
2054 }
2055 }
2056 Err(ErrorContext::new_missing(
2057 "ReplyAttrs",
2058 "Protocol",
2059 self.orig_loc,
2060 self.buf.as_ptr() as usize,
2061 ))
2062 }
2063 #[doc = "IPv6\\-only socket flag"]
2064 pub fn get_skv6only(&self) -> Result<(), ErrorContext> {
2065 let mut iter = self.clone();
2066 iter.pos = 0;
2067 for attr in iter {
2068 if let ReplyAttrs::Skv6only(val) = attr? {
2069 return Ok(val);
2070 }
2071 }
2072 Err(ErrorContext::new_missing(
2073 "ReplyAttrs",
2074 "Skv6only",
2075 self.orig_loc,
2076 self.buf.as_ptr() as usize,
2077 ))
2078 }
2079 #[doc = "Local addresses\\. SCTP thing\\."]
2080 pub fn get_locals(&self) -> Result<&'a [u8], ErrorContext> {
2081 let mut iter = self.clone();
2082 iter.pos = 0;
2083 for attr in iter {
2084 if let ReplyAttrs::Locals(val) = attr? {
2085 return Ok(val);
2086 }
2087 }
2088 Err(ErrorContext::new_missing(
2089 "ReplyAttrs",
2090 "Locals",
2091 self.orig_loc,
2092 self.buf.as_ptr() as usize,
2093 ))
2094 }
2095 #[doc = "Peer addresses\\. SCTP thing\\."]
2096 pub fn get_peers(&self) -> Result<&'a [u8], ErrorContext> {
2097 let mut iter = self.clone();
2098 iter.pos = 0;
2099 for attr in iter {
2100 if let ReplyAttrs::Peers(val) = attr? {
2101 return Ok(val);
2102 }
2103 }
2104 Err(ErrorContext::new_missing(
2105 "ReplyAttrs",
2106 "Peers",
2107 self.orig_loc,
2108 self.buf.as_ptr() as usize,
2109 ))
2110 }
2111 pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
2112 let mut iter = self.clone();
2113 iter.pos = 0;
2114 for attr in iter {
2115 if let ReplyAttrs::Pad(val) = attr? {
2116 return Ok(val);
2117 }
2118 }
2119 Err(ErrorContext::new_missing(
2120 "ReplyAttrs",
2121 "Pad",
2122 self.orig_loc,
2123 self.buf.as_ptr() as usize,
2124 ))
2125 }
2126 #[doc = "Socket mark (only with CAP\\_NET\\_ADMIN)"]
2127 pub fn get_mark(&self) -> Result<u32, ErrorContext> {
2128 let mut iter = self.clone();
2129 iter.pos = 0;
2130 for attr in iter {
2131 if let ReplyAttrs::Mark(val) = attr? {
2132 return Ok(val);
2133 }
2134 }
2135 Err(ErrorContext::new_missing(
2136 "ReplyAttrs",
2137 "Mark",
2138 self.orig_loc,
2139 self.buf.as_ptr() as usize,
2140 ))
2141 }
2142 #[doc = "TCP BBR information (request as INET\\_DIAG\\_VEGASINFO)"]
2143 pub fn get_bbritfo(&self) -> Result<TcpBbrInfo, ErrorContext> {
2144 let mut iter = self.clone();
2145 iter.pos = 0;
2146 for attr in iter {
2147 if let ReplyAttrs::Bbritfo(val) = attr? {
2148 return Ok(val);
2149 }
2150 }
2151 Err(ErrorContext::new_missing(
2152 "ReplyAttrs",
2153 "Bbritfo",
2154 self.orig_loc,
2155 self.buf.as_ptr() as usize,
2156 ))
2157 }
2158 #[doc = "Class ID (request as INET\\_DIAG\\_TCLASS)"]
2159 pub fn get_class_id(&self) -> Result<u32, ErrorContext> {
2160 let mut iter = self.clone();
2161 iter.pos = 0;
2162 for attr in iter {
2163 if let ReplyAttrs::ClassId(val) = attr? {
2164 return Ok(val);
2165 }
2166 }
2167 Err(ErrorContext::new_missing(
2168 "ReplyAttrs",
2169 "ClassId",
2170 self.orig_loc,
2171 self.buf.as_ptr() as usize,
2172 ))
2173 }
2174 #[doc = "MD5 signature information"]
2175 pub fn get_md5sig(&self) -> Result<&'a [u8], ErrorContext> {
2176 let mut iter = self.clone();
2177 iter.pos = 0;
2178 for attr in iter {
2179 if let ReplyAttrs::Md5sig(val) = attr? {
2180 return Ok(val);
2181 }
2182 }
2183 Err(ErrorContext::new_missing(
2184 "ReplyAttrs",
2185 "Md5sig",
2186 self.orig_loc,
2187 self.buf.as_ptr() as usize,
2188 ))
2189 }
2190 #[doc = "Upper Layer Protocol information"]
2191 pub fn get_ulp_info(&self) -> Result<IterableUlpInfoAttrs<'a>, ErrorContext> {
2192 let mut iter = self.clone();
2193 iter.pos = 0;
2194 for attr in iter {
2195 if let ReplyAttrs::UlpInfo(val) = attr? {
2196 return Ok(val);
2197 }
2198 }
2199 Err(ErrorContext::new_missing(
2200 "ReplyAttrs",
2201 "UlpInfo",
2202 self.orig_loc,
2203 self.buf.as_ptr() as usize,
2204 ))
2205 }
2206 #[doc = "BPF storage information\nAttribute may repeat multiple times (treat it as array)"]
2207 pub fn get_sk_bpf_storages(
2208 &self,
2209 ) -> MultiAttrIterable<Self, ReplyAttrs<'a>, IterableBpfStorageReply<'a>> {
2210 MultiAttrIterable::new(self.clone(), |variant| {
2211 if let ReplyAttrs::SkBpfStorages(val) = variant {
2212 Some(val)
2213 } else {
2214 None
2215 }
2216 })
2217 }
2218 #[doc = "Cgroup ID"]
2219 pub fn get_cgroup_id(&self) -> Result<u64, ErrorContext> {
2220 let mut iter = self.clone();
2221 iter.pos = 0;
2222 for attr in iter {
2223 if let ReplyAttrs::CgroupId(val) = attr? {
2224 return Ok(val);
2225 }
2226 }
2227 Err(ErrorContext::new_missing(
2228 "ReplyAttrs",
2229 "CgroupId",
2230 self.orig_loc,
2231 self.buf.as_ptr() as usize,
2232 ))
2233 }
2234 #[doc = "Socket options\nAssociated type: [`SockoptFlag`] (enum)"]
2235 pub fn get_sockopt_flags(&self) -> Result<u16, ErrorContext> {
2236 let mut iter = self.clone();
2237 iter.pos = 0;
2238 for attr in iter {
2239 if let ReplyAttrs::SockoptFlags(val) = attr? {
2240 return Ok(val);
2241 }
2242 }
2243 Err(ErrorContext::new_missing(
2244 "ReplyAttrs",
2245 "SockoptFlags",
2246 self.orig_loc,
2247 self.buf.as_ptr() as usize,
2248 ))
2249 }
2250}
2251impl ReplyAttrs<'_> {
2252 pub fn new<'a>(buf: &'a [u8]) -> IterableReplyAttrs<'a> {
2253 IterableReplyAttrs::with_loc(buf, buf.as_ptr() as usize)
2254 }
2255 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2256 let res = match r#type {
2257 1u16 => "Meminfo",
2258 2u16 => "TcpInfo",
2259 3u16 => "Vegasinfo",
2260 4u16 => "Cong",
2261 5u16 => "Tos",
2262 6u16 => "Tclass",
2263 7u16 => "Skmeminfo",
2264 8u16 => "Shutdown",
2265 9u16 => "Dctcpinfo",
2266 10u16 => "Protocol",
2267 11u16 => "Skv6only",
2268 12u16 => "Locals",
2269 13u16 => "Peers",
2270 14u16 => "Pad",
2271 15u16 => "Mark",
2272 16u16 => "Bbritfo",
2273 17u16 => "ClassId",
2274 18u16 => "Md5sig",
2275 19u16 => "UlpInfo",
2276 20u16 => "SkBpfStorages",
2277 21u16 => "CgroupId",
2278 22u16 => "SockoptFlags",
2279 _ => return None,
2280 };
2281 Some(res)
2282 }
2283}
2284#[derive(Clone, Copy, Default)]
2285pub struct IterableReplyAttrs<'a> {
2286 buf: &'a [u8],
2287 pos: usize,
2288 orig_loc: usize,
2289}
2290impl<'a> IterableReplyAttrs<'a> {
2291 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2292 Self {
2293 buf,
2294 pos: 0,
2295 orig_loc,
2296 }
2297 }
2298 pub fn get_buf(&self) -> &'a [u8] {
2299 self.buf
2300 }
2301}
2302impl<'a> Iterator for IterableReplyAttrs<'a> {
2303 type Item = Result<ReplyAttrs<'a>, ErrorContext>;
2304 fn next(&mut self) -> Option<Self::Item> {
2305 let pos = self.pos;
2306 let mut r#type;
2307 loop {
2308 r#type = None;
2309 if self.buf.len() == self.pos {
2310 return None;
2311 }
2312 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2313 break;
2314 };
2315 r#type = Some(header.r#type);
2316 let res = match header.r#type {
2317 1u16 => ReplyAttrs::Meminfo({
2318 let res = Some(Meminfo::new_from_zeroed(next));
2319 let Some(val) = res else { break };
2320 val
2321 }),
2322 2u16 => ReplyAttrs::TcpInfo({
2323 let res = Some(TcpInfo::new_from_zeroed(next));
2324 let Some(val) = res else { break };
2325 val
2326 }),
2327 3u16 => ReplyAttrs::Vegasinfo({
2328 let res = Some(TcpvegasInfo::new_from_zeroed(next));
2329 let Some(val) = res else { break };
2330 val
2331 }),
2332 4u16 => ReplyAttrs::Cong({
2333 let res = CStr::from_bytes_with_nul(next).ok();
2334 let Some(val) = res else { break };
2335 val
2336 }),
2337 5u16 => ReplyAttrs::Tos({
2338 let res = parse_u8(next);
2339 let Some(val) = res else { break };
2340 val
2341 }),
2342 6u16 => ReplyAttrs::Tclass({
2343 let res = parse_u8(next);
2344 let Some(val) = res else { break };
2345 val
2346 }),
2347 7u16 => ReplyAttrs::Skmeminfo({
2348 let res = Some(next);
2349 let Some(val) = res else { break };
2350 val
2351 }),
2352 8u16 => ReplyAttrs::Shutdown({
2353 let res = parse_u8(next);
2354 let Some(val) = res else { break };
2355 val
2356 }),
2357 9u16 => ReplyAttrs::Dctcpinfo({
2358 let res = Some(TcpDctcpInfo::new_from_zeroed(next));
2359 let Some(val) = res else { break };
2360 val
2361 }),
2362 10u16 => ReplyAttrs::Protocol({
2363 let res = parse_u8(next);
2364 let Some(val) = res else { break };
2365 val
2366 }),
2367 11u16 => ReplyAttrs::Skv6only(()),
2368 12u16 => ReplyAttrs::Locals({
2369 let res = Some(next);
2370 let Some(val) = res else { break };
2371 val
2372 }),
2373 13u16 => ReplyAttrs::Peers({
2374 let res = Some(next);
2375 let Some(val) = res else { break };
2376 val
2377 }),
2378 14u16 => ReplyAttrs::Pad({
2379 let res = Some(next);
2380 let Some(val) = res else { break };
2381 val
2382 }),
2383 15u16 => ReplyAttrs::Mark({
2384 let res = parse_u32(next);
2385 let Some(val) = res else { break };
2386 val
2387 }),
2388 16u16 => ReplyAttrs::Bbritfo({
2389 let res = Some(TcpBbrInfo::new_from_zeroed(next));
2390 let Some(val) = res else { break };
2391 val
2392 }),
2393 17u16 => ReplyAttrs::ClassId({
2394 let res = parse_u32(next);
2395 let Some(val) = res else { break };
2396 val
2397 }),
2398 18u16 => ReplyAttrs::Md5sig({
2399 let res = Some(next);
2400 let Some(val) = res else { break };
2401 val
2402 }),
2403 19u16 => ReplyAttrs::UlpInfo({
2404 let res = Some(IterableUlpInfoAttrs::with_loc(next, self.orig_loc));
2405 let Some(val) = res else { break };
2406 val
2407 }),
2408 20u16 => ReplyAttrs::SkBpfStorages({
2409 let res = Some(IterableBpfStorageReply::with_loc(next, self.orig_loc));
2410 let Some(val) = res else { break };
2411 val
2412 }),
2413 21u16 => ReplyAttrs::CgroupId({
2414 let res = parse_u64(next);
2415 let Some(val) = res else { break };
2416 val
2417 }),
2418 22u16 => ReplyAttrs::SockoptFlags({
2419 let res = parse_u16(next);
2420 let Some(val) = res else { break };
2421 val
2422 }),
2423 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2424 n => continue,
2425 };
2426 return Some(Ok(res));
2427 }
2428 Some(Err(ErrorContext::new(
2429 "ReplyAttrs",
2430 r#type.and_then(|t| ReplyAttrs::attr_from_type(t)),
2431 self.orig_loc,
2432 self.buf.as_ptr().wrapping_add(pos) as usize,
2433 )))
2434 }
2435}
2436impl<'a> std::fmt::Debug for IterableReplyAttrs<'_> {
2437 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2438 let mut fmt = f.debug_struct("ReplyAttrs");
2439 for attr in self.clone() {
2440 let attr = match attr {
2441 Ok(a) => a,
2442 Err(err) => {
2443 fmt.finish()?;
2444 f.write_str("Err(")?;
2445 err.fmt(f)?;
2446 return f.write_str(")");
2447 }
2448 };
2449 match attr {
2450 ReplyAttrs::Meminfo(val) => fmt.field("Meminfo", &val),
2451 ReplyAttrs::TcpInfo(val) => fmt.field("TcpInfo", &val),
2452 ReplyAttrs::Vegasinfo(val) => fmt.field("Vegasinfo", &val),
2453 ReplyAttrs::Cong(val) => fmt.field("Cong", &val),
2454 ReplyAttrs::Tos(val) => fmt.field("Tos", &val),
2455 ReplyAttrs::Tclass(val) => fmt.field("Tclass", &val),
2456 ReplyAttrs::Skmeminfo(val) => fmt.field("Skmeminfo", &val),
2457 ReplyAttrs::Shutdown(val) => fmt.field("Shutdown", &val),
2458 ReplyAttrs::Dctcpinfo(val) => fmt.field("Dctcpinfo", &val),
2459 ReplyAttrs::Protocol(val) => fmt.field("Protocol", &val),
2460 ReplyAttrs::Skv6only(val) => fmt.field("Skv6only", &val),
2461 ReplyAttrs::Locals(val) => fmt.field("Locals", &val),
2462 ReplyAttrs::Peers(val) => fmt.field("Peers", &val),
2463 ReplyAttrs::Pad(val) => fmt.field("Pad", &val),
2464 ReplyAttrs::Mark(val) => fmt.field("Mark", &val),
2465 ReplyAttrs::Bbritfo(val) => fmt.field("Bbritfo", &val),
2466 ReplyAttrs::ClassId(val) => fmt.field("ClassId", &val),
2467 ReplyAttrs::Md5sig(val) => fmt.field("Md5sig", &val),
2468 ReplyAttrs::UlpInfo(val) => fmt.field("UlpInfo", &val),
2469 ReplyAttrs::SkBpfStorages(val) => fmt.field("SkBpfStorages", &val),
2470 ReplyAttrs::CgroupId(val) => fmt.field("CgroupId", &val),
2471 ReplyAttrs::SockoptFlags(val) => fmt.field(
2472 "SockoptFlags",
2473 &FormatFlags(val.into(), SockoptFlag::from_value),
2474 ),
2475 };
2476 }
2477 fmt.finish()
2478 }
2479}
2480impl IterableReplyAttrs<'_> {
2481 pub fn lookup_attr(
2482 &self,
2483 offset: usize,
2484 missing_type: Option<u16>,
2485 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2486 let mut stack = Vec::new();
2487 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2488 if missing_type.is_some() && cur == offset {
2489 stack.push(("ReplyAttrs", offset));
2490 return (
2491 stack,
2492 missing_type.and_then(|t| ReplyAttrs::attr_from_type(t)),
2493 );
2494 }
2495 if cur > offset || cur + self.buf.len() < offset {
2496 return (stack, None);
2497 }
2498 let mut attrs = self.clone();
2499 let mut last_off = cur + attrs.pos;
2500 let mut missing = None;
2501 while let Some(attr) = attrs.next() {
2502 let Ok(attr) = attr else { break };
2503 match attr {
2504 ReplyAttrs::Meminfo(val) => {
2505 if last_off == offset {
2506 stack.push(("Meminfo", last_off));
2507 break;
2508 }
2509 }
2510 ReplyAttrs::TcpInfo(val) => {
2511 if last_off == offset {
2512 stack.push(("TcpInfo", last_off));
2513 break;
2514 }
2515 }
2516 ReplyAttrs::Vegasinfo(val) => {
2517 if last_off == offset {
2518 stack.push(("Vegasinfo", last_off));
2519 break;
2520 }
2521 }
2522 ReplyAttrs::Cong(val) => {
2523 if last_off == offset {
2524 stack.push(("Cong", last_off));
2525 break;
2526 }
2527 }
2528 ReplyAttrs::Tos(val) => {
2529 if last_off == offset {
2530 stack.push(("Tos", last_off));
2531 break;
2532 }
2533 }
2534 ReplyAttrs::Tclass(val) => {
2535 if last_off == offset {
2536 stack.push(("Tclass", last_off));
2537 break;
2538 }
2539 }
2540 ReplyAttrs::Skmeminfo(val) => {
2541 if last_off == offset {
2542 stack.push(("Skmeminfo", last_off));
2543 break;
2544 }
2545 }
2546 ReplyAttrs::Shutdown(val) => {
2547 if last_off == offset {
2548 stack.push(("Shutdown", last_off));
2549 break;
2550 }
2551 }
2552 ReplyAttrs::Dctcpinfo(val) => {
2553 if last_off == offset {
2554 stack.push(("Dctcpinfo", last_off));
2555 break;
2556 }
2557 }
2558 ReplyAttrs::Protocol(val) => {
2559 if last_off == offset {
2560 stack.push(("Protocol", last_off));
2561 break;
2562 }
2563 }
2564 ReplyAttrs::Skv6only(val) => {
2565 if last_off == offset {
2566 stack.push(("Skv6only", last_off));
2567 break;
2568 }
2569 }
2570 ReplyAttrs::Locals(val) => {
2571 if last_off == offset {
2572 stack.push(("Locals", last_off));
2573 break;
2574 }
2575 }
2576 ReplyAttrs::Peers(val) => {
2577 if last_off == offset {
2578 stack.push(("Peers", last_off));
2579 break;
2580 }
2581 }
2582 ReplyAttrs::Pad(val) => {
2583 if last_off == offset {
2584 stack.push(("Pad", last_off));
2585 break;
2586 }
2587 }
2588 ReplyAttrs::Mark(val) => {
2589 if last_off == offset {
2590 stack.push(("Mark", last_off));
2591 break;
2592 }
2593 }
2594 ReplyAttrs::Bbritfo(val) => {
2595 if last_off == offset {
2596 stack.push(("Bbritfo", last_off));
2597 break;
2598 }
2599 }
2600 ReplyAttrs::ClassId(val) => {
2601 if last_off == offset {
2602 stack.push(("ClassId", last_off));
2603 break;
2604 }
2605 }
2606 ReplyAttrs::Md5sig(val) => {
2607 if last_off == offset {
2608 stack.push(("Md5sig", last_off));
2609 break;
2610 }
2611 }
2612 ReplyAttrs::UlpInfo(val) => {
2613 (stack, missing) = val.lookup_attr(offset, missing_type);
2614 if !stack.is_empty() {
2615 break;
2616 }
2617 }
2618 ReplyAttrs::SkBpfStorages(val) => {
2619 (stack, missing) = val.lookup_attr(offset, missing_type);
2620 if !stack.is_empty() {
2621 break;
2622 }
2623 }
2624 ReplyAttrs::CgroupId(val) => {
2625 if last_off == offset {
2626 stack.push(("CgroupId", last_off));
2627 break;
2628 }
2629 }
2630 ReplyAttrs::SockoptFlags(val) => {
2631 if last_off == offset {
2632 stack.push(("SockoptFlags", last_off));
2633 break;
2634 }
2635 }
2636 _ => {}
2637 };
2638 last_off = cur + attrs.pos;
2639 }
2640 if !stack.is_empty() {
2641 stack.push(("ReplyAttrs", cur));
2642 }
2643 (stack, missing)
2644 }
2645}
2646#[derive(Clone)]
2647pub enum BpfStorageReq {
2648 #[doc = "Attribute may repeat multiple times (treat it as array)"]
2649 MapFd(u32),
2650}
2651impl<'a> IterableBpfStorageReq<'a> {
2652 #[doc = "Attribute may repeat multiple times (treat it as array)"]
2653 pub fn get_map_fd(&self) -> MultiAttrIterable<Self, BpfStorageReq, u32> {
2654 MultiAttrIterable::new(self.clone(), |variant| {
2655 if let BpfStorageReq::MapFd(val) = variant {
2656 Some(val)
2657 } else {
2658 None
2659 }
2660 })
2661 }
2662}
2663impl BpfStorageReq {
2664 pub fn new<'a>(buf: &'a [u8]) -> IterableBpfStorageReq<'a> {
2665 IterableBpfStorageReq::with_loc(buf, buf.as_ptr() as usize)
2666 }
2667 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2668 let res = match r#type {
2669 1u16 => "MapFd",
2670 _ => return None,
2671 };
2672 Some(res)
2673 }
2674}
2675#[derive(Clone, Copy, Default)]
2676pub struct IterableBpfStorageReq<'a> {
2677 buf: &'a [u8],
2678 pos: usize,
2679 orig_loc: usize,
2680}
2681impl<'a> IterableBpfStorageReq<'a> {
2682 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2683 Self {
2684 buf,
2685 pos: 0,
2686 orig_loc,
2687 }
2688 }
2689 pub fn get_buf(&self) -> &'a [u8] {
2690 self.buf
2691 }
2692}
2693impl<'a> Iterator for IterableBpfStorageReq<'a> {
2694 type Item = Result<BpfStorageReq, ErrorContext>;
2695 fn next(&mut self) -> Option<Self::Item> {
2696 let pos = self.pos;
2697 let mut r#type;
2698 loop {
2699 r#type = None;
2700 if self.buf.len() == self.pos {
2701 return None;
2702 }
2703 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2704 break;
2705 };
2706 r#type = Some(header.r#type);
2707 let res = match header.r#type {
2708 1u16 => BpfStorageReq::MapFd({
2709 let res = parse_u32(next);
2710 let Some(val) = res else { break };
2711 val
2712 }),
2713 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2714 n => continue,
2715 };
2716 return Some(Ok(res));
2717 }
2718 Some(Err(ErrorContext::new(
2719 "BpfStorageReq",
2720 r#type.and_then(|t| BpfStorageReq::attr_from_type(t)),
2721 self.orig_loc,
2722 self.buf.as_ptr().wrapping_add(pos) as usize,
2723 )))
2724 }
2725}
2726impl std::fmt::Debug for IterableBpfStorageReq<'_> {
2727 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2728 let mut fmt = f.debug_struct("BpfStorageReq");
2729 for attr in self.clone() {
2730 let attr = match attr {
2731 Ok(a) => a,
2732 Err(err) => {
2733 fmt.finish()?;
2734 f.write_str("Err(")?;
2735 err.fmt(f)?;
2736 return f.write_str(")");
2737 }
2738 };
2739 match attr {
2740 BpfStorageReq::MapFd(val) => fmt.field("MapFd", &val),
2741 };
2742 }
2743 fmt.finish()
2744 }
2745}
2746impl IterableBpfStorageReq<'_> {
2747 pub fn lookup_attr(
2748 &self,
2749 offset: usize,
2750 missing_type: Option<u16>,
2751 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2752 let mut stack = Vec::new();
2753 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2754 if missing_type.is_some() && cur == offset {
2755 stack.push(("BpfStorageReq", offset));
2756 return (
2757 stack,
2758 missing_type.and_then(|t| BpfStorageReq::attr_from_type(t)),
2759 );
2760 }
2761 if cur > offset || cur + self.buf.len() < offset {
2762 return (stack, None);
2763 }
2764 let mut attrs = self.clone();
2765 let mut last_off = cur + attrs.pos;
2766 while let Some(attr) = attrs.next() {
2767 let Ok(attr) = attr else { break };
2768 match attr {
2769 BpfStorageReq::MapFd(val) => {
2770 if last_off == offset {
2771 stack.push(("MapFd", last_off));
2772 break;
2773 }
2774 }
2775 _ => {}
2776 };
2777 last_off = cur + attrs.pos;
2778 }
2779 if !stack.is_empty() {
2780 stack.push(("BpfStorageReq", cur));
2781 }
2782 (stack, None)
2783 }
2784}
2785#[derive(Clone)]
2786pub enum BpfStorageReply<'a> {
2787 Storage(IterableBpfStorage<'a>),
2788}
2789impl<'a> IterableBpfStorageReply<'a> {
2790 pub fn get_storage(&self) -> Result<IterableBpfStorage<'a>, ErrorContext> {
2791 let mut iter = self.clone();
2792 iter.pos = 0;
2793 for attr in iter {
2794 if let BpfStorageReply::Storage(val) = attr? {
2795 return Ok(val);
2796 }
2797 }
2798 Err(ErrorContext::new_missing(
2799 "BpfStorageReply",
2800 "Storage",
2801 self.orig_loc,
2802 self.buf.as_ptr() as usize,
2803 ))
2804 }
2805}
2806impl BpfStorageReply<'_> {
2807 pub fn new<'a>(buf: &'a [u8]) -> IterableBpfStorageReply<'a> {
2808 IterableBpfStorageReply::with_loc(buf, buf.as_ptr() as usize)
2809 }
2810 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2811 let res = match r#type {
2812 1u16 => "Storage",
2813 _ => return None,
2814 };
2815 Some(res)
2816 }
2817}
2818#[derive(Clone, Copy, Default)]
2819pub struct IterableBpfStorageReply<'a> {
2820 buf: &'a [u8],
2821 pos: usize,
2822 orig_loc: usize,
2823}
2824impl<'a> IterableBpfStorageReply<'a> {
2825 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2826 Self {
2827 buf,
2828 pos: 0,
2829 orig_loc,
2830 }
2831 }
2832 pub fn get_buf(&self) -> &'a [u8] {
2833 self.buf
2834 }
2835}
2836impl<'a> Iterator for IterableBpfStorageReply<'a> {
2837 type Item = Result<BpfStorageReply<'a>, ErrorContext>;
2838 fn next(&mut self) -> Option<Self::Item> {
2839 let pos = self.pos;
2840 let mut r#type;
2841 loop {
2842 r#type = None;
2843 if self.buf.len() == self.pos {
2844 return None;
2845 }
2846 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2847 break;
2848 };
2849 r#type = Some(header.r#type);
2850 let res = match header.r#type {
2851 1u16 => BpfStorageReply::Storage({
2852 let res = Some(IterableBpfStorage::with_loc(next, self.orig_loc));
2853 let Some(val) = res else { break };
2854 val
2855 }),
2856 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2857 n => continue,
2858 };
2859 return Some(Ok(res));
2860 }
2861 Some(Err(ErrorContext::new(
2862 "BpfStorageReply",
2863 r#type.and_then(|t| BpfStorageReply::attr_from_type(t)),
2864 self.orig_loc,
2865 self.buf.as_ptr().wrapping_add(pos) as usize,
2866 )))
2867 }
2868}
2869impl<'a> std::fmt::Debug for IterableBpfStorageReply<'_> {
2870 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2871 let mut fmt = f.debug_struct("BpfStorageReply");
2872 for attr in self.clone() {
2873 let attr = match attr {
2874 Ok(a) => a,
2875 Err(err) => {
2876 fmt.finish()?;
2877 f.write_str("Err(")?;
2878 err.fmt(f)?;
2879 return f.write_str(")");
2880 }
2881 };
2882 match attr {
2883 BpfStorageReply::Storage(val) => fmt.field("Storage", &val),
2884 };
2885 }
2886 fmt.finish()
2887 }
2888}
2889impl IterableBpfStorageReply<'_> {
2890 pub fn lookup_attr(
2891 &self,
2892 offset: usize,
2893 missing_type: Option<u16>,
2894 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2895 let mut stack = Vec::new();
2896 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2897 if missing_type.is_some() && cur == offset {
2898 stack.push(("BpfStorageReply", offset));
2899 return (
2900 stack,
2901 missing_type.and_then(|t| BpfStorageReply::attr_from_type(t)),
2902 );
2903 }
2904 if cur > offset || cur + self.buf.len() < offset {
2905 return (stack, None);
2906 }
2907 let mut attrs = self.clone();
2908 let mut last_off = cur + attrs.pos;
2909 let mut missing = None;
2910 while let Some(attr) = attrs.next() {
2911 let Ok(attr) = attr else { break };
2912 match attr {
2913 BpfStorageReply::Storage(val) => {
2914 (stack, missing) = val.lookup_attr(offset, missing_type);
2915 if !stack.is_empty() {
2916 break;
2917 }
2918 }
2919 _ => {}
2920 };
2921 last_off = cur + attrs.pos;
2922 }
2923 if !stack.is_empty() {
2924 stack.push(("BpfStorageReply", cur));
2925 }
2926 (stack, missing)
2927 }
2928}
2929#[derive(Clone)]
2930pub enum BpfStorage<'a> {
2931 Pad(&'a [u8]),
2932 MapId(u32),
2933 MapValue(u64),
2934}
2935impl<'a> IterableBpfStorage<'a> {
2936 pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
2937 let mut iter = self.clone();
2938 iter.pos = 0;
2939 for attr in iter {
2940 if let BpfStorage::Pad(val) = attr? {
2941 return Ok(val);
2942 }
2943 }
2944 Err(ErrorContext::new_missing(
2945 "BpfStorage",
2946 "Pad",
2947 self.orig_loc,
2948 self.buf.as_ptr() as usize,
2949 ))
2950 }
2951 pub fn get_map_id(&self) -> Result<u32, ErrorContext> {
2952 let mut iter = self.clone();
2953 iter.pos = 0;
2954 for attr in iter {
2955 if let BpfStorage::MapId(val) = attr? {
2956 return Ok(val);
2957 }
2958 }
2959 Err(ErrorContext::new_missing(
2960 "BpfStorage",
2961 "MapId",
2962 self.orig_loc,
2963 self.buf.as_ptr() as usize,
2964 ))
2965 }
2966 pub fn get_map_value(&self) -> Result<u64, ErrorContext> {
2967 let mut iter = self.clone();
2968 iter.pos = 0;
2969 for attr in iter {
2970 if let BpfStorage::MapValue(val) = attr? {
2971 return Ok(val);
2972 }
2973 }
2974 Err(ErrorContext::new_missing(
2975 "BpfStorage",
2976 "MapValue",
2977 self.orig_loc,
2978 self.buf.as_ptr() as usize,
2979 ))
2980 }
2981}
2982impl BpfStorage<'_> {
2983 pub fn new<'a>(buf: &'a [u8]) -> IterableBpfStorage<'a> {
2984 IterableBpfStorage::with_loc(buf, buf.as_ptr() as usize)
2985 }
2986 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2987 let res = match r#type {
2988 1u16 => "Pad",
2989 2u16 => "MapId",
2990 3u16 => "MapValue",
2991 _ => return None,
2992 };
2993 Some(res)
2994 }
2995}
2996#[derive(Clone, Copy, Default)]
2997pub struct IterableBpfStorage<'a> {
2998 buf: &'a [u8],
2999 pos: usize,
3000 orig_loc: usize,
3001}
3002impl<'a> IterableBpfStorage<'a> {
3003 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3004 Self {
3005 buf,
3006 pos: 0,
3007 orig_loc,
3008 }
3009 }
3010 pub fn get_buf(&self) -> &'a [u8] {
3011 self.buf
3012 }
3013}
3014impl<'a> Iterator for IterableBpfStorage<'a> {
3015 type Item = Result<BpfStorage<'a>, ErrorContext>;
3016 fn next(&mut self) -> Option<Self::Item> {
3017 let pos = self.pos;
3018 let mut r#type;
3019 loop {
3020 r#type = None;
3021 if self.buf.len() == self.pos {
3022 return None;
3023 }
3024 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3025 break;
3026 };
3027 r#type = Some(header.r#type);
3028 let res = match header.r#type {
3029 1u16 => BpfStorage::Pad({
3030 let res = Some(next);
3031 let Some(val) = res else { break };
3032 val
3033 }),
3034 2u16 => BpfStorage::MapId({
3035 let res = parse_u32(next);
3036 let Some(val) = res else { break };
3037 val
3038 }),
3039 3u16 => BpfStorage::MapValue({
3040 let res = parse_u64(next);
3041 let Some(val) = res else { break };
3042 val
3043 }),
3044 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3045 n => continue,
3046 };
3047 return Some(Ok(res));
3048 }
3049 Some(Err(ErrorContext::new(
3050 "BpfStorage",
3051 r#type.and_then(|t| BpfStorage::attr_from_type(t)),
3052 self.orig_loc,
3053 self.buf.as_ptr().wrapping_add(pos) as usize,
3054 )))
3055 }
3056}
3057impl<'a> std::fmt::Debug for IterableBpfStorage<'_> {
3058 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3059 let mut fmt = f.debug_struct("BpfStorage");
3060 for attr in self.clone() {
3061 let attr = match attr {
3062 Ok(a) => a,
3063 Err(err) => {
3064 fmt.finish()?;
3065 f.write_str("Err(")?;
3066 err.fmt(f)?;
3067 return f.write_str(")");
3068 }
3069 };
3070 match attr {
3071 BpfStorage::Pad(val) => fmt.field("Pad", &val),
3072 BpfStorage::MapId(val) => fmt.field("MapId", &val),
3073 BpfStorage::MapValue(val) => fmt.field("MapValue", &val),
3074 };
3075 }
3076 fmt.finish()
3077 }
3078}
3079impl IterableBpfStorage<'_> {
3080 pub fn lookup_attr(
3081 &self,
3082 offset: usize,
3083 missing_type: Option<u16>,
3084 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3085 let mut stack = Vec::new();
3086 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3087 if missing_type.is_some() && cur == offset {
3088 stack.push(("BpfStorage", offset));
3089 return (
3090 stack,
3091 missing_type.and_then(|t| BpfStorage::attr_from_type(t)),
3092 );
3093 }
3094 if cur > offset || cur + self.buf.len() < offset {
3095 return (stack, None);
3096 }
3097 let mut attrs = self.clone();
3098 let mut last_off = cur + attrs.pos;
3099 while let Some(attr) = attrs.next() {
3100 let Ok(attr) = attr else { break };
3101 match attr {
3102 BpfStorage::Pad(val) => {
3103 if last_off == offset {
3104 stack.push(("Pad", last_off));
3105 break;
3106 }
3107 }
3108 BpfStorage::MapId(val) => {
3109 if last_off == offset {
3110 stack.push(("MapId", last_off));
3111 break;
3112 }
3113 }
3114 BpfStorage::MapValue(val) => {
3115 if last_off == offset {
3116 stack.push(("MapValue", last_off));
3117 break;
3118 }
3119 }
3120 _ => {}
3121 };
3122 last_off = cur + attrs.pos;
3123 }
3124 if !stack.is_empty() {
3125 stack.push(("BpfStorage", cur));
3126 }
3127 (stack, None)
3128 }
3129}
3130pub struct PushUlpInfoAttrs<Prev: Rec> {
3131 pub(crate) prev: Option<Prev>,
3132 pub(crate) header_offset: Option<usize>,
3133}
3134impl<Prev: Rec> Rec for PushUlpInfoAttrs<Prev> {
3135 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3136 self.prev.as_mut().unwrap().as_rec_mut()
3137 }
3138 fn as_rec(&self) -> &Vec<u8> {
3139 self.prev.as_ref().unwrap().as_rec()
3140 }
3141}
3142impl<Prev: Rec> PushUlpInfoAttrs<Prev> {
3143 pub fn new(prev: Prev) -> Self {
3144 Self {
3145 prev: Some(prev),
3146 header_offset: None,
3147 }
3148 }
3149 pub fn end_nested(mut self) -> Prev {
3150 let mut prev = self.prev.take().unwrap();
3151 if let Some(header_offset) = &self.header_offset {
3152 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3153 }
3154 prev
3155 }
3156 #[doc = "ULP name (e\\.g\\., \"tls\", \"mptcp\")"]
3157 pub fn push_name(mut self, value: &CStr) -> Self {
3158 push_header(
3159 self.as_rec_mut(),
3160 1u16,
3161 value.to_bytes_with_nul().len() as u16,
3162 );
3163 self.as_rec_mut().extend(value.to_bytes_with_nul());
3164 self
3165 }
3166 #[doc = "ULP name (e\\.g\\., \"tls\", \"mptcp\")"]
3167 pub fn push_name_bytes(mut self, value: &[u8]) -> Self {
3168 push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
3169 self.as_rec_mut().extend(value);
3170 self.as_rec_mut().push(0);
3171 self
3172 }
3173 #[doc = "TLS\\-specific information"]
3174 pub fn push_tls(mut self, value: &[u8]) -> Self {
3175 push_header(self.as_rec_mut(), 2u16, value.len() as u16);
3176 self.as_rec_mut().extend(value);
3177 self
3178 }
3179 #[doc = "MPTCP\\-specific information"]
3180 pub fn push_mptcp(mut self, value: &[u8]) -> Self {
3181 push_header(self.as_rec_mut(), 3u16, value.len() as u16);
3182 self.as_rec_mut().extend(value);
3183 self
3184 }
3185}
3186impl<Prev: Rec> Drop for PushUlpInfoAttrs<Prev> {
3187 fn drop(&mut self) {
3188 if let Some(prev) = &mut self.prev {
3189 if let Some(header_offset) = &self.header_offset {
3190 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3191 }
3192 }
3193 }
3194}
3195pub struct PushRequestAttrs<Prev: Rec> {
3196 pub(crate) prev: Option<Prev>,
3197 pub(crate) header_offset: Option<usize>,
3198}
3199impl<Prev: Rec> Rec for PushRequestAttrs<Prev> {
3200 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3201 self.prev.as_mut().unwrap().as_rec_mut()
3202 }
3203 fn as_rec(&self) -> &Vec<u8> {
3204 self.prev.as_ref().unwrap().as_rec()
3205 }
3206}
3207impl<Prev: Rec> PushRequestAttrs<Prev> {
3208 pub fn new(prev: Prev) -> Self {
3209 Self {
3210 prev: Some(prev),
3211 header_offset: None,
3212 }
3213 }
3214 pub fn end_nested(mut self) -> Prev {
3215 let mut prev = self.prev.take().unwrap();
3216 if let Some(header_offset) = &self.header_offset {
3217 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3218 }
3219 prev
3220 }
3221 #[doc = "See bytecode\\-op"]
3222 pub fn push_bytecode(mut self, value: &[u8]) -> Self {
3223 push_header(self.as_rec_mut(), 1u16, value.len() as u16);
3224 self.as_rec_mut().extend(value);
3225 self
3226 }
3227 pub fn nested_bpf_storages(mut self) -> PushBpfStorageReq<Self> {
3228 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
3229 PushBpfStorageReq {
3230 prev: Some(self),
3231 header_offset: Some(header_offset),
3232 }
3233 }
3234 pub fn push_protocol(mut self, value: u32) -> Self {
3235 push_header(self.as_rec_mut(), 3u16, 4 as u16);
3236 self.as_rec_mut().extend(value.to_ne_bytes());
3237 self
3238 }
3239}
3240impl<Prev: Rec> Drop for PushRequestAttrs<Prev> {
3241 fn drop(&mut self) {
3242 if let Some(prev) = &mut self.prev {
3243 if let Some(header_offset) = &self.header_offset {
3244 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3245 }
3246 }
3247 }
3248}
3249pub struct PushReplyAttrs<Prev: Rec> {
3250 pub(crate) prev: Option<Prev>,
3251 pub(crate) header_offset: Option<usize>,
3252}
3253impl<Prev: Rec> Rec for PushReplyAttrs<Prev> {
3254 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3255 self.prev.as_mut().unwrap().as_rec_mut()
3256 }
3257 fn as_rec(&self) -> &Vec<u8> {
3258 self.prev.as_ref().unwrap().as_rec()
3259 }
3260}
3261impl<Prev: Rec> PushReplyAttrs<Prev> {
3262 pub fn new(prev: Prev) -> Self {
3263 Self {
3264 prev: Some(prev),
3265 header_offset: None,
3266 }
3267 }
3268 pub fn end_nested(mut self) -> Prev {
3269 let mut prev = self.prev.take().unwrap();
3270 if let Some(header_offset) = &self.header_offset {
3271 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3272 }
3273 prev
3274 }
3275 #[doc = "Memory information extension"]
3276 pub fn push_meminfo(mut self, value: Meminfo) -> Self {
3277 push_header(self.as_rec_mut(), 1u16, value.as_slice().len() as u16);
3278 self.as_rec_mut().extend(value.as_slice());
3279 self
3280 }
3281 pub fn push_tcp_info(mut self, value: TcpInfo) -> Self {
3282 push_header(self.as_rec_mut(), 2u16, value.as_slice().len() as u16);
3283 self.as_rec_mut().extend(value.as_slice());
3284 self
3285 }
3286 #[doc = "TCP Vegas information"]
3287 pub fn push_vegasinfo(mut self, value: TcpvegasInfo) -> Self {
3288 push_header(self.as_rec_mut(), 3u16, value.as_slice().len() as u16);
3289 self.as_rec_mut().extend(value.as_slice());
3290 self
3291 }
3292 #[doc = "Congestion control algorithm name"]
3293 pub fn push_cong(mut self, value: &CStr) -> Self {
3294 push_header(
3295 self.as_rec_mut(),
3296 4u16,
3297 value.to_bytes_with_nul().len() as u16,
3298 );
3299 self.as_rec_mut().extend(value.to_bytes_with_nul());
3300 self
3301 }
3302 #[doc = "Congestion control algorithm name"]
3303 pub fn push_cong_bytes(mut self, value: &[u8]) -> Self {
3304 push_header(self.as_rec_mut(), 4u16, (value.len() + 1) as u16);
3305 self.as_rec_mut().extend(value);
3306 self.as_rec_mut().push(0);
3307 self
3308 }
3309 #[doc = "Type of Service"]
3310 pub fn push_tos(mut self, value: u8) -> Self {
3311 push_header(self.as_rec_mut(), 5u16, 1 as u16);
3312 self.as_rec_mut().extend(value.to_ne_bytes());
3313 self
3314 }
3315 #[doc = "Traffic Class"]
3316 pub fn push_tclass(mut self, value: u8) -> Self {
3317 push_header(self.as_rec_mut(), 6u16, 1 as u16);
3318 self.as_rec_mut().extend(value.to_ne_bytes());
3319 self
3320 }
3321 #[doc = "Socket memory information"]
3322 pub fn push_skmeminfo(mut self, value: &[u8]) -> Self {
3323 push_header(self.as_rec_mut(), 7u16, value.len() as u16);
3324 self.as_rec_mut().extend(value);
3325 self
3326 }
3327 #[doc = "Shutdown state"]
3328 pub fn push_shutdown(mut self, value: u8) -> Self {
3329 push_header(self.as_rec_mut(), 8u16, 1 as u16);
3330 self.as_rec_mut().extend(value.to_ne_bytes());
3331 self
3332 }
3333 #[doc = "TCP DCTCP information (request as INET\\_DIAG\\_VEGASINFO)"]
3334 pub fn push_dctcpinfo(mut self, value: TcpDctcpInfo) -> Self {
3335 push_header(self.as_rec_mut(), 9u16, value.as_slice().len() as u16);
3336 self.as_rec_mut().extend(value.as_slice());
3337 self
3338 }
3339 #[doc = "Raw socket protocol (response attribute only)"]
3340 pub fn push_protocol(mut self, value: u8) -> Self {
3341 push_header(self.as_rec_mut(), 10u16, 1 as u16);
3342 self.as_rec_mut().extend(value.to_ne_bytes());
3343 self
3344 }
3345 #[doc = "IPv6\\-only socket flag"]
3346 pub fn push_skv6only(mut self, value: ()) -> Self {
3347 push_header(self.as_rec_mut(), 11u16, 0 as u16);
3348 self
3349 }
3350 #[doc = "Local addresses\\. SCTP thing\\."]
3351 pub fn push_locals(mut self, value: &[u8]) -> Self {
3352 push_header(self.as_rec_mut(), 12u16, value.len() as u16);
3353 self.as_rec_mut().extend(value);
3354 self
3355 }
3356 #[doc = "Peer addresses\\. SCTP thing\\."]
3357 pub fn push_peers(mut self, value: &[u8]) -> Self {
3358 push_header(self.as_rec_mut(), 13u16, value.len() as u16);
3359 self.as_rec_mut().extend(value);
3360 self
3361 }
3362 pub fn push_pad(mut self, value: &[u8]) -> Self {
3363 push_header(self.as_rec_mut(), 14u16, value.len() as u16);
3364 self.as_rec_mut().extend(value);
3365 self
3366 }
3367 #[doc = "Socket mark (only with CAP\\_NET\\_ADMIN)"]
3368 pub fn push_mark(mut self, value: u32) -> Self {
3369 push_header(self.as_rec_mut(), 15u16, 4 as u16);
3370 self.as_rec_mut().extend(value.to_ne_bytes());
3371 self
3372 }
3373 #[doc = "TCP BBR information (request as INET\\_DIAG\\_VEGASINFO)"]
3374 pub fn push_bbritfo(mut self, value: TcpBbrInfo) -> Self {
3375 push_header(self.as_rec_mut(), 16u16, value.as_slice().len() as u16);
3376 self.as_rec_mut().extend(value.as_slice());
3377 self
3378 }
3379 #[doc = "Class ID (request as INET\\_DIAG\\_TCLASS)"]
3380 pub fn push_class_id(mut self, value: u32) -> Self {
3381 push_header(self.as_rec_mut(), 17u16, 4 as u16);
3382 self.as_rec_mut().extend(value.to_ne_bytes());
3383 self
3384 }
3385 #[doc = "MD5 signature information"]
3386 pub fn push_md5sig(mut self, value: &[u8]) -> Self {
3387 push_header(self.as_rec_mut(), 18u16, value.len() as u16);
3388 self.as_rec_mut().extend(value);
3389 self
3390 }
3391 #[doc = "Upper Layer Protocol information"]
3392 pub fn nested_ulp_info(mut self) -> PushUlpInfoAttrs<Self> {
3393 let header_offset = push_nested_header(self.as_rec_mut(), 19u16);
3394 PushUlpInfoAttrs {
3395 prev: Some(self),
3396 header_offset: Some(header_offset),
3397 }
3398 }
3399 #[doc = "BPF storage information\nAttribute may repeat multiple times (treat it as array)"]
3400 pub fn nested_sk_bpf_storages(mut self) -> PushBpfStorageReply<Self> {
3401 let header_offset = push_nested_header(self.as_rec_mut(), 20u16);
3402 PushBpfStorageReply {
3403 prev: Some(self),
3404 header_offset: Some(header_offset),
3405 }
3406 }
3407 #[doc = "Cgroup ID"]
3408 pub fn push_cgroup_id(mut self, value: u64) -> Self {
3409 push_header(self.as_rec_mut(), 21u16, 8 as u16);
3410 self.as_rec_mut().extend(value.to_ne_bytes());
3411 self
3412 }
3413 #[doc = "Socket options\nAssociated type: [`SockoptFlag`] (enum)"]
3414 pub fn push_sockopt_flags(mut self, value: u16) -> Self {
3415 push_header(self.as_rec_mut(), 22u16, 2 as u16);
3416 self.as_rec_mut().extend(value.to_ne_bytes());
3417 self
3418 }
3419}
3420impl<Prev: Rec> Drop for PushReplyAttrs<Prev> {
3421 fn drop(&mut self) {
3422 if let Some(prev) = &mut self.prev {
3423 if let Some(header_offset) = &self.header_offset {
3424 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3425 }
3426 }
3427 }
3428}
3429pub struct PushBpfStorageReq<Prev: Rec> {
3430 pub(crate) prev: Option<Prev>,
3431 pub(crate) header_offset: Option<usize>,
3432}
3433impl<Prev: Rec> Rec for PushBpfStorageReq<Prev> {
3434 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3435 self.prev.as_mut().unwrap().as_rec_mut()
3436 }
3437 fn as_rec(&self) -> &Vec<u8> {
3438 self.prev.as_ref().unwrap().as_rec()
3439 }
3440}
3441impl<Prev: Rec> PushBpfStorageReq<Prev> {
3442 pub fn new(prev: Prev) -> Self {
3443 Self {
3444 prev: Some(prev),
3445 header_offset: None,
3446 }
3447 }
3448 pub fn end_nested(mut self) -> Prev {
3449 let mut prev = self.prev.take().unwrap();
3450 if let Some(header_offset) = &self.header_offset {
3451 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3452 }
3453 prev
3454 }
3455 #[doc = "Attribute may repeat multiple times (treat it as array)"]
3456 pub fn push_map_fd(mut self, value: u32) -> Self {
3457 push_header(self.as_rec_mut(), 1u16, 4 as u16);
3458 self.as_rec_mut().extend(value.to_ne_bytes());
3459 self
3460 }
3461}
3462impl<Prev: Rec> Drop for PushBpfStorageReq<Prev> {
3463 fn drop(&mut self) {
3464 if let Some(prev) = &mut self.prev {
3465 if let Some(header_offset) = &self.header_offset {
3466 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3467 }
3468 }
3469 }
3470}
3471pub struct PushBpfStorageReply<Prev: Rec> {
3472 pub(crate) prev: Option<Prev>,
3473 pub(crate) header_offset: Option<usize>,
3474}
3475impl<Prev: Rec> Rec for PushBpfStorageReply<Prev> {
3476 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3477 self.prev.as_mut().unwrap().as_rec_mut()
3478 }
3479 fn as_rec(&self) -> &Vec<u8> {
3480 self.prev.as_ref().unwrap().as_rec()
3481 }
3482}
3483impl<Prev: Rec> PushBpfStorageReply<Prev> {
3484 pub fn new(prev: Prev) -> Self {
3485 Self {
3486 prev: Some(prev),
3487 header_offset: None,
3488 }
3489 }
3490 pub fn end_nested(mut self) -> Prev {
3491 let mut prev = self.prev.take().unwrap();
3492 if let Some(header_offset) = &self.header_offset {
3493 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3494 }
3495 prev
3496 }
3497 pub fn nested_storage(mut self) -> PushBpfStorage<Self> {
3498 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
3499 PushBpfStorage {
3500 prev: Some(self),
3501 header_offset: Some(header_offset),
3502 }
3503 }
3504}
3505impl<Prev: Rec> Drop for PushBpfStorageReply<Prev> {
3506 fn drop(&mut self) {
3507 if let Some(prev) = &mut self.prev {
3508 if let Some(header_offset) = &self.header_offset {
3509 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3510 }
3511 }
3512 }
3513}
3514pub struct PushBpfStorage<Prev: Rec> {
3515 pub(crate) prev: Option<Prev>,
3516 pub(crate) header_offset: Option<usize>,
3517}
3518impl<Prev: Rec> Rec for PushBpfStorage<Prev> {
3519 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3520 self.prev.as_mut().unwrap().as_rec_mut()
3521 }
3522 fn as_rec(&self) -> &Vec<u8> {
3523 self.prev.as_ref().unwrap().as_rec()
3524 }
3525}
3526impl<Prev: Rec> PushBpfStorage<Prev> {
3527 pub fn new(prev: Prev) -> Self {
3528 Self {
3529 prev: Some(prev),
3530 header_offset: None,
3531 }
3532 }
3533 pub fn end_nested(mut self) -> Prev {
3534 let mut prev = self.prev.take().unwrap();
3535 if let Some(header_offset) = &self.header_offset {
3536 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3537 }
3538 prev
3539 }
3540 pub fn push_pad(mut self, value: &[u8]) -> Self {
3541 push_header(self.as_rec_mut(), 1u16, value.len() as u16);
3542 self.as_rec_mut().extend(value);
3543 self
3544 }
3545 pub fn push_map_id(mut self, value: u32) -> Self {
3546 push_header(self.as_rec_mut(), 2u16, 4 as u16);
3547 self.as_rec_mut().extend(value.to_ne_bytes());
3548 self
3549 }
3550 pub fn push_map_value(mut self, value: u64) -> Self {
3551 push_header(self.as_rec_mut(), 3u16, 8 as u16);
3552 self.as_rec_mut().extend(value.to_ne_bytes());
3553 self
3554 }
3555}
3556impl<Prev: Rec> Drop for PushBpfStorage<Prev> {
3557 fn drop(&mut self) {
3558 if let Some(prev) = &mut self.prev {
3559 if let Some(header_offset) = &self.header_offset {
3560 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3561 }
3562 }
3563 }
3564}
3565#[doc = ""]
3566#[derive(Debug)]
3567pub struct OpTcpDiagDump<'r> {
3568 request: Request<'r>,
3569}
3570impl<'r> OpTcpDiagDump<'r> {
3571 pub fn new(mut request: Request<'r>, header: &ReqV2) -> Self {
3572 Self::write_header(request.buf_mut(), header);
3573 Self {
3574 request: request.set_dump(),
3575 }
3576 }
3577 pub fn encode_request<'buf>(
3578 buf: &'buf mut Vec<u8>,
3579 header: &ReqV2,
3580 ) -> PushRequestAttrs<&'buf mut Vec<u8>> {
3581 Self::write_header(buf, header);
3582 PushRequestAttrs::new(buf)
3583 }
3584 pub fn encode(&mut self) -> PushRequestAttrs<&mut Vec<u8>> {
3585 PushRequestAttrs::new(self.request.buf_mut())
3586 }
3587 pub fn into_encoder(self) -> PushRequestAttrs<RequestBuf<'r>> {
3588 PushRequestAttrs::new(self.request.buf)
3589 }
3590 pub fn decode_request<'a>(buf: &'a [u8]) -> (ReqV2, IterableRequestAttrs<'a>) {
3591 let (header, attrs) = buf.split_at(buf.len().min(ReqV2::len()));
3592 (
3593 ReqV2::new_from_slice(header).unwrap_or_default(),
3594 IterableRequestAttrs::with_loc(attrs, buf.as_ptr() as usize),
3595 )
3596 }
3597 fn decode_reply<'a>(buf: &'a [u8]) -> (Msg, IterableReplyAttrs<'a>) {
3598 let (header, attrs) = buf.split_at(buf.len().min(Msg::len()));
3599 (
3600 Msg::new_from_slice(header).unwrap_or_default(),
3601 IterableReplyAttrs::with_loc(attrs, buf.as_ptr() as usize),
3602 )
3603 }
3604 fn write_header<Prev: Rec>(prev: &mut Prev, header: &ReqV2) {
3605 prev.as_rec_mut().extend(header.as_slice());
3606 }
3607}
3608impl NetlinkRequest for OpTcpDiagDump<'_> {
3609 fn protocol(&self) -> Protocol {
3610 Protocol::Raw {
3611 protonum: 4u16,
3612 request_type: 20u16,
3613 }
3614 }
3615 fn flags(&self) -> u16 {
3616 self.request.flags
3617 }
3618 fn payload(&self) -> &[u8] {
3619 self.request.buf()
3620 }
3621 type ReplyType<'buf> = (Msg, IterableReplyAttrs<'buf>);
3622 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
3623 Self::decode_reply(buf)
3624 }
3625 fn lookup(
3626 buf: &[u8],
3627 offset: usize,
3628 missing_type: Option<u16>,
3629 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3630 Self::decode_request(buf)
3631 .1
3632 .lookup_attr(offset, missing_type)
3633 }
3634}
3635#[doc = ""]
3636#[derive(Debug)]
3637pub struct OpUdpDiagDump<'r> {
3638 request: Request<'r>,
3639}
3640impl<'r> OpUdpDiagDump<'r> {
3641 pub fn new(mut request: Request<'r>, header: &ReqV2) -> Self {
3642 Self::write_header(request.buf_mut(), header);
3643 Self {
3644 request: request.set_dump(),
3645 }
3646 }
3647 pub fn encode_request<'buf>(
3648 buf: &'buf mut Vec<u8>,
3649 header: &ReqV2,
3650 ) -> PushRequestAttrs<&'buf mut Vec<u8>> {
3651 Self::write_header(buf, header);
3652 PushRequestAttrs::new(buf)
3653 }
3654 pub fn encode(&mut self) -> PushRequestAttrs<&mut Vec<u8>> {
3655 PushRequestAttrs::new(self.request.buf_mut())
3656 }
3657 pub fn into_encoder(self) -> PushRequestAttrs<RequestBuf<'r>> {
3658 PushRequestAttrs::new(self.request.buf)
3659 }
3660 pub fn decode_request<'a>(buf: &'a [u8]) -> (ReqV2, IterableRequestAttrs<'a>) {
3661 let (header, attrs) = buf.split_at(buf.len().min(ReqV2::len()));
3662 (
3663 ReqV2::new_from_slice(header).unwrap_or_default(),
3664 IterableRequestAttrs::with_loc(attrs, buf.as_ptr() as usize),
3665 )
3666 }
3667 fn decode_reply<'a>(buf: &'a [u8]) -> (Msg, IterableReplyAttrs<'a>) {
3668 let (header, attrs) = buf.split_at(buf.len().min(Msg::len()));
3669 (
3670 Msg::new_from_slice(header).unwrap_or_default(),
3671 IterableReplyAttrs::with_loc(attrs, buf.as_ptr() as usize),
3672 )
3673 }
3674 fn write_header<Prev: Rec>(prev: &mut Prev, header: &ReqV2) {
3675 prev.as_rec_mut().extend(header.as_slice());
3676 }
3677}
3678impl NetlinkRequest for OpUdpDiagDump<'_> {
3679 fn protocol(&self) -> Protocol {
3680 Protocol::Raw {
3681 protonum: 4u16,
3682 request_type: 20u16,
3683 }
3684 }
3685 fn flags(&self) -> u16 {
3686 self.request.flags
3687 }
3688 fn payload(&self) -> &[u8] {
3689 self.request.buf()
3690 }
3691 type ReplyType<'buf> = (Msg, IterableReplyAttrs<'buf>);
3692 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
3693 Self::decode_reply(buf)
3694 }
3695 fn lookup(
3696 buf: &[u8],
3697 offset: usize,
3698 missing_type: Option<u16>,
3699 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3700 Self::decode_request(buf)
3701 .1
3702 .lookup_attr(offset, missing_type)
3703 }
3704}
3705#[derive(Debug)]
3706pub struct ChainedFinal<'a> {
3707 inner: Chained<'a>,
3708}
3709#[derive(Debug)]
3710pub struct Chained<'a> {
3711 buf: RequestBuf<'a>,
3712 first_seq: u32,
3713 lookups: Vec<(&'static str, LookupFn)>,
3714 last_header_offset: usize,
3715 last_kind: Option<RequestInfo>,
3716}
3717impl<'a> ChainedFinal<'a> {
3718 pub fn into_chained(self) -> Chained<'a> {
3719 self.inner
3720 }
3721 pub fn buf(&self) -> &Vec<u8> {
3722 self.inner.buf()
3723 }
3724 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3725 self.inner.buf_mut()
3726 }
3727 fn get_index(&self, seq: u32) -> Option<u32> {
3728 let min = self.inner.first_seq;
3729 let max = min.wrapping_add(self.inner.lookups.len() as u32);
3730 return if min <= max {
3731 (min..max).contains(&seq).then(|| seq - min)
3732 } else if min <= seq {
3733 Some(seq - min)
3734 } else if seq < max {
3735 Some(u32::MAX - min + seq)
3736 } else {
3737 None
3738 };
3739 }
3740}
3741impl crate::traits::NetlinkChained for ChainedFinal<'_> {
3742 fn protonum(&self) -> u16 {
3743 PROTONUM
3744 }
3745 fn payload(&self) -> &[u8] {
3746 self.buf()
3747 }
3748 fn chain_len(&self) -> usize {
3749 self.inner.lookups.len()
3750 }
3751 fn get_index(&self, seq: u32) -> Option<usize> {
3752 self.get_index(seq).map(|n| n as usize)
3753 }
3754 fn name(&self, index: usize) -> &'static str {
3755 self.inner.lookups[index].0
3756 }
3757 fn lookup(&self, index: usize) -> LookupFn {
3758 self.inner.lookups[index].1
3759 }
3760}
3761impl Chained<'static> {
3762 pub fn new(first_seq: u32) -> Self {
3763 Self::new_from_buf(Vec::new(), first_seq)
3764 }
3765 pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
3766 Self {
3767 buf: RequestBuf::Own(buf),
3768 first_seq,
3769 lookups: Vec::new(),
3770 last_header_offset: 0,
3771 last_kind: None,
3772 }
3773 }
3774 pub fn into_buf(self) -> Vec<u8> {
3775 match self.buf {
3776 RequestBuf::Own(buf) => buf,
3777 _ => unreachable!(),
3778 }
3779 }
3780}
3781impl<'a> Chained<'a> {
3782 pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
3783 Self {
3784 buf: RequestBuf::Ref(buf),
3785 first_seq,
3786 lookups: Vec::new(),
3787 last_header_offset: 0,
3788 last_kind: None,
3789 }
3790 }
3791 pub fn finalize(mut self) -> ChainedFinal<'a> {
3792 self.update_header();
3793 ChainedFinal { inner: self }
3794 }
3795 pub fn request(&mut self) -> Request<'_> {
3796 self.update_header();
3797 self.last_header_offset = self.buf().len();
3798 self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
3799 let mut request = Request::new_extend(self.buf.buf_mut());
3800 self.last_kind = None;
3801 request.writeback = Some(&mut self.last_kind);
3802 request
3803 }
3804 pub fn buf(&self) -> &Vec<u8> {
3805 self.buf.buf()
3806 }
3807 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3808 self.buf.buf_mut()
3809 }
3810 fn update_header(&mut self) {
3811 let Some(RequestInfo {
3812 protocol,
3813 flags,
3814 name,
3815 lookup,
3816 }) = self.last_kind
3817 else {
3818 if !self.buf().is_empty() {
3819 assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
3820 self.buf.buf_mut().truncate(self.last_header_offset);
3821 }
3822 return;
3823 };
3824 let header_offset = self.last_header_offset;
3825 let request_type = match protocol {
3826 Protocol::Raw { request_type, .. } => request_type,
3827 Protocol::Generic(_) => unreachable!(),
3828 };
3829 let index = self.lookups.len();
3830 let seq = self.first_seq.wrapping_add(index as u32);
3831 self.lookups.push((name, lookup));
3832 let buf = self.buf_mut();
3833 align(buf);
3834 let header = Nlmsghdr {
3835 len: (buf.len() - header_offset) as u32,
3836 r#type: request_type,
3837 flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
3838 seq,
3839 pid: 0,
3840 };
3841 buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
3842 }
3843}
3844use crate::traits::LookupFn;
3845use crate::utils::RequestBuf;
3846#[derive(Debug)]
3847pub struct Request<'buf> {
3848 buf: RequestBuf<'buf>,
3849 flags: u16,
3850 writeback: Option<&'buf mut Option<RequestInfo>>,
3851}
3852#[allow(unused)]
3853#[derive(Debug, Clone)]
3854pub struct RequestInfo {
3855 protocol: Protocol,
3856 flags: u16,
3857 name: &'static str,
3858 lookup: LookupFn,
3859}
3860impl Request<'static> {
3861 pub fn new() -> Self {
3862 Self::new_from_buf(Vec::new())
3863 }
3864 pub fn new_from_buf(buf: Vec<u8>) -> Self {
3865 Self {
3866 flags: 0,
3867 buf: RequestBuf::Own(buf),
3868 writeback: None,
3869 }
3870 }
3871 pub fn into_buf(self) -> Vec<u8> {
3872 match self.buf {
3873 RequestBuf::Own(buf) => buf,
3874 _ => unreachable!(),
3875 }
3876 }
3877}
3878impl<'buf> Request<'buf> {
3879 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
3880 buf.clear();
3881 Self::new_extend(buf)
3882 }
3883 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
3884 Self {
3885 flags: 0,
3886 buf: RequestBuf::Ref(buf),
3887 writeback: None,
3888 }
3889 }
3890 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
3891 let Some(writeback) = &mut self.writeback else {
3892 return;
3893 };
3894 **writeback = Some(RequestInfo {
3895 protocol,
3896 flags: self.flags,
3897 name,
3898 lookup,
3899 })
3900 }
3901 pub fn buf(&self) -> &Vec<u8> {
3902 self.buf.buf()
3903 }
3904 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3905 self.buf.buf_mut()
3906 }
3907 #[doc = "Set `NLM_F_CREATE` flag"]
3908 pub fn set_create(mut self) -> Self {
3909 self.flags |= consts::NLM_F_CREATE as u16;
3910 self
3911 }
3912 #[doc = "Set `NLM_F_EXCL` flag"]
3913 pub fn set_excl(mut self) -> Self {
3914 self.flags |= consts::NLM_F_EXCL as u16;
3915 self
3916 }
3917 #[doc = "Set `NLM_F_REPLACE` flag"]
3918 pub fn set_replace(mut self) -> Self {
3919 self.flags |= consts::NLM_F_REPLACE as u16;
3920 self
3921 }
3922 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
3923 pub fn set_change(self) -> Self {
3924 self.set_create().set_replace()
3925 }
3926 #[doc = "Set `NLM_F_APPEND` flag"]
3927 pub fn set_append(mut self) -> Self {
3928 self.flags |= consts::NLM_F_APPEND as u16;
3929 self
3930 }
3931 #[doc = "Set `self.flags |= flags`"]
3932 pub fn set_flags(mut self, flags: u16) -> Self {
3933 self.flags |= flags;
3934 self
3935 }
3936 #[doc = "Set `self.flags ^= self.flags & flags`"]
3937 pub fn unset_flags(mut self, flags: u16) -> Self {
3938 self.flags ^= self.flags & flags;
3939 self
3940 }
3941 #[doc = "Set `NLM_F_DUMP` flag"]
3942 fn set_dump(mut self) -> Self {
3943 self.flags |= consts::NLM_F_DUMP as u16;
3944 self
3945 }
3946 #[doc = ""]
3947 pub fn op_tcp_diag_dump(self, header: &ReqV2) -> OpTcpDiagDump<'buf> {
3948 let mut res = OpTcpDiagDump::new(self, header);
3949 res.request
3950 .do_writeback(res.protocol(), "op-tcp-diag-dump", OpTcpDiagDump::lookup);
3951 res
3952 }
3953 #[doc = ""]
3954 pub fn op_udp_diag_dump(self, header: &ReqV2) -> OpUdpDiagDump<'buf> {
3955 let mut res = OpUdpDiagDump::new(self, header);
3956 res.request
3957 .do_writeback(res.protocol(), "op-udp-diag-dump", OpUdpDiagDump::lookup);
3958 res
3959 }
3960}