Skip to main content

netlink_bindings/inet-diag/
mod.rs

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: Rec> {
3143    pub(crate) prev: Option<Prev>,
3144    pub(crate) header_offset: Option<usize>,
3145}
3146impl<Prev: Rec> Rec for PushUlpInfoAttrs<Prev> {
3147    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3148        self.prev.as_mut().unwrap().as_rec_mut()
3149    }
3150    fn as_rec(&self) -> &Vec<u8> {
3151        self.prev.as_ref().unwrap().as_rec()
3152    }
3153}
3154impl<Prev: Rec> 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_rec_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_rec_mut(),
3172            1u16,
3173            value.to_bytes_with_nul().len() as u16,
3174        );
3175        self.as_rec_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_rec_mut(), 1u16, (value.len() + 1) as u16);
3181        self.as_rec_mut().extend(value);
3182        self.as_rec_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_rec_mut(), 2u16, value.len() as u16);
3188        self.as_rec_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_rec_mut(), 3u16, value.len() as u16);
3194        self.as_rec_mut().extend(value);
3195        self
3196    }
3197}
3198impl<Prev: Rec> 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_rec_mut(), *header_offset);
3203            }
3204        }
3205    }
3206}
3207pub struct PushRequestAttrs<Prev: Rec> {
3208    pub(crate) prev: Option<Prev>,
3209    pub(crate) header_offset: Option<usize>,
3210}
3211impl<Prev: Rec> Rec for PushRequestAttrs<Prev> {
3212    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3213        self.prev.as_mut().unwrap().as_rec_mut()
3214    }
3215    fn as_rec(&self) -> &Vec<u8> {
3216        self.prev.as_ref().unwrap().as_rec()
3217    }
3218}
3219impl<Prev: Rec> 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_rec_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_rec_mut(), 1u16, value.len() as u16);
3236        self.as_rec_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_rec_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_rec_mut(), 3u16, 4 as u16);
3248        self.as_rec_mut().extend(value.to_ne_bytes());
3249        self
3250    }
3251}
3252impl<Prev: Rec> 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_rec_mut(), *header_offset);
3257            }
3258        }
3259    }
3260}
3261pub struct PushReplyAttrs<Prev: Rec> {
3262    pub(crate) prev: Option<Prev>,
3263    pub(crate) header_offset: Option<usize>,
3264}
3265impl<Prev: Rec> Rec for PushReplyAttrs<Prev> {
3266    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3267        self.prev.as_mut().unwrap().as_rec_mut()
3268    }
3269    fn as_rec(&self) -> &Vec<u8> {
3270        self.prev.as_ref().unwrap().as_rec()
3271    }
3272}
3273impl<Prev: Rec> 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_rec_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_rec_mut(), 1u16, value.as_slice().len() as u16);
3290        self.as_rec_mut().extend(value.as_slice());
3291        self
3292    }
3293    pub fn push_tcp_info(mut self, value: TcpInfo) -> Self {
3294        push_header(self.as_rec_mut(), 2u16, value.as_slice().len() as u16);
3295        self.as_rec_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_rec_mut(), 3u16, value.as_slice().len() as u16);
3301        self.as_rec_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_rec_mut(),
3308            4u16,
3309            value.to_bytes_with_nul().len() as u16,
3310        );
3311        self.as_rec_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_rec_mut(), 4u16, (value.len() + 1) as u16);
3317        self.as_rec_mut().extend(value);
3318        self.as_rec_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_rec_mut(), 5u16, 1 as u16);
3324        self.as_rec_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_rec_mut(), 6u16, 1 as u16);
3330        self.as_rec_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_rec_mut(), 7u16, value.len() as u16);
3336        self.as_rec_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_rec_mut(), 8u16, 1 as u16);
3342        self.as_rec_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_rec_mut(), 9u16, value.as_slice().len() as u16);
3348        self.as_rec_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_rec_mut(), 10u16, 1 as u16);
3354        self.as_rec_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_rec_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_rec_mut(), 12u16, value.len() as u16);
3365        self.as_rec_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_rec_mut(), 13u16, value.len() as u16);
3371        self.as_rec_mut().extend(value);
3372        self
3373    }
3374    pub fn push_pad(mut self, value: &[u8]) -> Self {
3375        push_header(self.as_rec_mut(), 14u16, value.len() as u16);
3376        self.as_rec_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_rec_mut(), 15u16, 4 as u16);
3382        self.as_rec_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_rec_mut(), 16u16, value.as_slice().len() as u16);
3388        self.as_rec_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_rec_mut(), 17u16, 4 as u16);
3394        self.as_rec_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_rec_mut(), 18u16, value.len() as u16);
3400        self.as_rec_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_rec_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_rec_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_rec_mut(), 21u16, 8 as u16);
3422        self.as_rec_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_rec_mut(), 22u16, 2 as u16);
3428        self.as_rec_mut().extend(value.to_ne_bytes());
3429        self
3430    }
3431}
3432impl<Prev: Rec> 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_rec_mut(), *header_offset);
3437            }
3438        }
3439    }
3440}
3441pub struct PushBpfStorageReq<Prev: Rec> {
3442    pub(crate) prev: Option<Prev>,
3443    pub(crate) header_offset: Option<usize>,
3444}
3445impl<Prev: Rec> Rec for PushBpfStorageReq<Prev> {
3446    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3447        self.prev.as_mut().unwrap().as_rec_mut()
3448    }
3449    fn as_rec(&self) -> &Vec<u8> {
3450        self.prev.as_ref().unwrap().as_rec()
3451    }
3452}
3453impl<Prev: Rec> 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_rec_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_rec_mut(), 1u16, 4 as u16);
3470        self.as_rec_mut().extend(value.to_ne_bytes());
3471        self
3472    }
3473}
3474impl<Prev: Rec> 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_rec_mut(), *header_offset);
3479            }
3480        }
3481    }
3482}
3483pub struct PushBpfStorageReply<Prev: Rec> {
3484    pub(crate) prev: Option<Prev>,
3485    pub(crate) header_offset: Option<usize>,
3486}
3487impl<Prev: Rec> Rec for PushBpfStorageReply<Prev> {
3488    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3489        self.prev.as_mut().unwrap().as_rec_mut()
3490    }
3491    fn as_rec(&self) -> &Vec<u8> {
3492        self.prev.as_ref().unwrap().as_rec()
3493    }
3494}
3495impl<Prev: Rec> 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_rec_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_rec_mut(), 1u16);
3511        PushBpfStorage {
3512            prev: Some(self),
3513            header_offset: Some(header_offset),
3514        }
3515    }
3516}
3517impl<Prev: Rec> 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_rec_mut(), *header_offset);
3522            }
3523        }
3524    }
3525}
3526pub struct PushBpfStorage<Prev: Rec> {
3527    pub(crate) prev: Option<Prev>,
3528    pub(crate) header_offset: Option<usize>,
3529}
3530impl<Prev: Rec> Rec for PushBpfStorage<Prev> {
3531    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3532        self.prev.as_mut().unwrap().as_rec_mut()
3533    }
3534    fn as_rec(&self) -> &Vec<u8> {
3535        self.prev.as_ref().unwrap().as_rec()
3536    }
3537}
3538impl<Prev: Rec> 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_rec_mut(), *header_offset);
3549        }
3550        prev
3551    }
3552    pub fn push_pad(mut self, value: &[u8]) -> Self {
3553        push_header(self.as_rec_mut(), 1u16, value.len() as u16);
3554        self.as_rec_mut().extend(value);
3555        self
3556    }
3557    pub fn push_map_id(mut self, value: u32) -> Self {
3558        push_header(self.as_rec_mut(), 2u16, 4 as u16);
3559        self.as_rec_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_rec_mut(), 3u16, 8 as u16);
3564        self.as_rec_mut().extend(value.to_ne_bytes());
3565        self
3566    }
3567}
3568impl<Prev: Rec> 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_rec_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: Rec>(prev: &mut Prev, header: &ReqV2) {
3617        prev.as_rec_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: Rec>(prev: &mut Prev, header: &ReqV2) {
3687        prev.as_rec_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}