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