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