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