Skip to main content

netlink_bindings/conntrack/
mod.rs

1#![doc = "Netfilter connection tracking subsystem over nfnetlink"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "conntrack";
17pub const PROTONAME_CSTR: &CStr = c"conntrack";
18pub const PROTONUM: u16 = 12u16;
19#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
20#[derive(Debug, Clone, Copy)]
21pub enum NfCtTcpFlags {
22    WindowScale = 1 << 0,
23    SackPerm = 1 << 1,
24    CloseInit = 1 << 2,
25    BeLiberal = 1 << 3,
26    Unacked = 1 << 4,
27    Maxack = 1 << 5,
28    ChallengeAck = 1 << 6,
29    SimultaneousOpen = 1 << 7,
30}
31impl NfCtTcpFlags {
32    pub fn from_value(value: u64) -> Option<Self> {
33        Some(match value {
34            n if n == 1 << 0 => Self::WindowScale,
35            n if n == 1 << 1 => Self::SackPerm,
36            n if n == 1 << 2 => Self::CloseInit,
37            n if n == 1 << 3 => Self::BeLiberal,
38            n if n == 1 << 4 => Self::Unacked,
39            n if n == 1 << 5 => Self::Maxack,
40            n if n == 1 << 6 => Self::ChallengeAck,
41            n if n == 1 << 7 => Self::SimultaneousOpen,
42            _ => return None,
43        })
44    }
45}
46#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
47#[derive(Debug, Clone, Copy)]
48pub enum NfCtTcpState {
49    None = 0,
50    SynSent = 1,
51    SynRecv = 2,
52    Established = 3,
53    FinWait = 4,
54    CloseWait = 5,
55    LastAck = 6,
56    TimeWait = 7,
57    Close = 8,
58    SynSent2 = 9,
59    Max = 10,
60    Ignore = 11,
61    Retrans = 12,
62    Unack = 13,
63    TimeoutMax = 14,
64}
65impl NfCtTcpState {
66    pub fn from_value(value: u64) -> Option<Self> {
67        Some(match value {
68            0 => Self::None,
69            1 => Self::SynSent,
70            2 => Self::SynRecv,
71            3 => Self::Established,
72            4 => Self::FinWait,
73            5 => Self::CloseWait,
74            6 => Self::LastAck,
75            7 => Self::TimeWait,
76            8 => Self::Close,
77            9 => Self::SynSent2,
78            10 => Self::Max,
79            11 => Self::Ignore,
80            12 => Self::Retrans,
81            13 => Self::Unack,
82            14 => Self::TimeoutMax,
83            _ => return None,
84        })
85    }
86}
87#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
88#[derive(Debug, Clone, Copy)]
89pub enum NfCtSctpState {
90    None = 0,
91    Cloned = 1,
92    CookieWait = 2,
93    CookieEchoed = 3,
94    Established = 4,
95    ShutdownSent = 5,
96    ShutdownReceived = 6,
97    ShutdownAckSent = 7,
98    ShutdownHeartbeatSent = 8,
99}
100impl NfCtSctpState {
101    pub fn from_value(value: u64) -> Option<Self> {
102        Some(match value {
103            0 => Self::None,
104            1 => Self::Cloned,
105            2 => Self::CookieWait,
106            3 => Self::CookieEchoed,
107            4 => Self::Established,
108            5 => Self::ShutdownSent,
109            6 => Self::ShutdownReceived,
110            7 => Self::ShutdownAckSent,
111            8 => Self::ShutdownHeartbeatSent,
112            _ => return None,
113        })
114    }
115}
116#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
117#[derive(Debug, Clone, Copy)]
118pub enum NfCtStatus {
119    Expected = 1 << 0,
120    SeenReply = 1 << 1,
121    Assured = 1 << 2,
122    Confirmed = 1 << 3,
123    SrcNat = 1 << 4,
124    DstNat = 1 << 5,
125    SeqAdj = 1 << 6,
126    SrcNatDone = 1 << 7,
127    DstNatDone = 1 << 8,
128    Dying = 1 << 9,
129    FixedTimeout = 1 << 10,
130    Template = 1 << 11,
131    NatClash = 1 << 12,
132    Helper = 1 << 13,
133    Offload = 1 << 14,
134    HwOffload = 1 << 15,
135}
136impl NfCtStatus {
137    pub fn from_value(value: u64) -> Option<Self> {
138        Some(match value {
139            n if n == 1 << 0 => Self::Expected,
140            n if n == 1 << 1 => Self::SeenReply,
141            n if n == 1 << 2 => Self::Assured,
142            n if n == 1 << 3 => Self::Confirmed,
143            n if n == 1 << 4 => Self::SrcNat,
144            n if n == 1 << 5 => Self::DstNat,
145            n if n == 1 << 6 => Self::SeqAdj,
146            n if n == 1 << 7 => Self::SrcNatDone,
147            n if n == 1 << 8 => Self::DstNatDone,
148            n if n == 1 << 9 => Self::Dying,
149            n if n == 1 << 10 => Self::FixedTimeout,
150            n if n == 1 << 11 => Self::Template,
151            n if n == 1 << 12 => Self::NatClash,
152            n if n == 1 << 13 => Self::Helper,
153            n if n == 1 << 14 => Self::Offload,
154            n if n == 1 << 15 => Self::HwOffload,
155            _ => return None,
156        })
157    }
158}
159#[repr(C, packed(4))]
160pub struct Nfgenmsg {
161    pub nfgen_family: u8,
162    pub version: u8,
163    pub _res_id_be: u16,
164}
165impl Clone for Nfgenmsg {
166    fn clone(&self) -> Self {
167        Self::new_from_array(*self.as_array())
168    }
169}
170#[doc = "Create zero-initialized struct"]
171impl Default for Nfgenmsg {
172    fn default() -> Self {
173        Self::new()
174    }
175}
176impl Nfgenmsg {
177    #[doc = "Create zero-initialized struct"]
178    pub fn new() -> Self {
179        Self::new_from_array([0u8; Self::len()])
180    }
181    #[doc = "Copy from contents from slice"]
182    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
183        if other.len() != Self::len() {
184            return None;
185        }
186        let mut buf = [0u8; Self::len()];
187        buf.clone_from_slice(other);
188        Some(Self::new_from_array(buf))
189    }
190    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
191    pub fn new_from_zeroed(other: &[u8]) -> Self {
192        let mut buf = [0u8; Self::len()];
193        let len = buf.len().min(other.len());
194        buf[..len].clone_from_slice(&other[..len]);
195        Self::new_from_array(buf)
196    }
197    pub fn new_from_array(buf: [u8; 4usize]) -> Self {
198        unsafe { std::mem::transmute(buf) }
199    }
200    pub fn as_slice(&self) -> &[u8] {
201        unsafe {
202            let ptr: *const u8 = std::mem::transmute(self as *const Self);
203            std::slice::from_raw_parts(ptr, Self::len())
204        }
205    }
206    pub fn from_slice(buf: &[u8]) -> &Self {
207        assert!(buf.len() >= Self::len());
208        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
209        unsafe { std::mem::transmute(buf.as_ptr()) }
210    }
211    pub fn as_array(&self) -> &[u8; 4usize] {
212        unsafe { std::mem::transmute(self) }
213    }
214    pub fn from_array(buf: &[u8; 4usize]) -> &Self {
215        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
216        unsafe { std::mem::transmute(buf) }
217    }
218    pub fn into_array(self) -> [u8; 4usize] {
219        unsafe { std::mem::transmute(self) }
220    }
221    pub const fn len() -> usize {
222        const _: () = assert!(std::mem::size_of::<Nfgenmsg>() == 4usize);
223        4usize
224    }
225    pub fn res_id(&self) -> u16 {
226        u16::from_be(self._res_id_be)
227    }
228    pub fn set_res_id(&mut self, value: u16) {
229        self._res_id_be = value.to_be();
230    }
231}
232impl std::fmt::Debug for Nfgenmsg {
233    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234        fmt.debug_struct("Nfgenmsg")
235            .field("nfgen_family", &self.nfgen_family)
236            .field("version", &self.version)
237            .field("res_id", &self.res_id())
238            .finish()
239    }
240}
241#[repr(C, packed(4))]
242pub struct NfCtTcpFlagsMask {
243    #[doc = "Associated type: [`NfCtTcpFlags`] (1 bit per enumeration)"]
244    pub flags: u8,
245    #[doc = "Associated type: [`NfCtTcpFlags`] (1 bit per enumeration)"]
246    pub mask: u8,
247}
248impl Clone for NfCtTcpFlagsMask {
249    fn clone(&self) -> Self {
250        Self::new_from_array(*self.as_array())
251    }
252}
253#[doc = "Create zero-initialized struct"]
254impl Default for NfCtTcpFlagsMask {
255    fn default() -> Self {
256        Self::new()
257    }
258}
259impl NfCtTcpFlagsMask {
260    #[doc = "Create zero-initialized struct"]
261    pub fn new() -> Self {
262        Self::new_from_array([0u8; Self::len()])
263    }
264    #[doc = "Copy from contents from slice"]
265    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
266        if other.len() != Self::len() {
267            return None;
268        }
269        let mut buf = [0u8; Self::len()];
270        buf.clone_from_slice(other);
271        Some(Self::new_from_array(buf))
272    }
273    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
274    pub fn new_from_zeroed(other: &[u8]) -> Self {
275        let mut buf = [0u8; Self::len()];
276        let len = buf.len().min(other.len());
277        buf[..len].clone_from_slice(&other[..len]);
278        Self::new_from_array(buf)
279    }
280    pub fn new_from_array(buf: [u8; 2usize]) -> Self {
281        unsafe { std::mem::transmute(buf) }
282    }
283    pub fn as_slice(&self) -> &[u8] {
284        unsafe {
285            let ptr: *const u8 = std::mem::transmute(self as *const Self);
286            std::slice::from_raw_parts(ptr, Self::len())
287        }
288    }
289    pub fn from_slice(buf: &[u8]) -> &Self {
290        assert!(buf.len() >= Self::len());
291        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
292        unsafe { std::mem::transmute(buf.as_ptr()) }
293    }
294    pub fn as_array(&self) -> &[u8; 2usize] {
295        unsafe { std::mem::transmute(self) }
296    }
297    pub fn from_array(buf: &[u8; 2usize]) -> &Self {
298        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
299        unsafe { std::mem::transmute(buf) }
300    }
301    pub fn into_array(self) -> [u8; 2usize] {
302        unsafe { std::mem::transmute(self) }
303    }
304    pub const fn len() -> usize {
305        const _: () = assert!(std::mem::size_of::<NfCtTcpFlagsMask>() == 2usize);
306        2usize
307    }
308}
309impl std::fmt::Debug for NfCtTcpFlagsMask {
310    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
311        fmt.debug_struct("NfCtTcpFlagsMask")
312            .field(
313                "flags",
314                &FormatFlags(self.flags.into(), NfCtTcpFlags::from_value),
315            )
316            .field(
317                "mask",
318                &FormatFlags(self.mask.into(), NfCtTcpFlags::from_value),
319            )
320            .finish()
321    }
322}
323#[derive(Clone)]
324pub enum CounterAttrs<'a> {
325    Packets(u64),
326    Bytes(u64),
327    PacketsOld(u32),
328    BytesOld(u32),
329    Pad(&'a [u8]),
330}
331impl<'a> IterableCounterAttrs<'a> {
332    pub fn get_packets(&self) -> Result<u64, ErrorContext> {
333        let mut iter = self.clone();
334        iter.pos = 0;
335        for attr in iter {
336            if let CounterAttrs::Packets(val) = attr? {
337                return Ok(val);
338            }
339        }
340        Err(ErrorContext::new_missing(
341            "CounterAttrs",
342            "Packets",
343            self.orig_loc,
344            self.buf.as_ptr() as usize,
345        ))
346    }
347    pub fn get_bytes(&self) -> Result<u64, ErrorContext> {
348        let mut iter = self.clone();
349        iter.pos = 0;
350        for attr in iter {
351            if let CounterAttrs::Bytes(val) = attr? {
352                return Ok(val);
353            }
354        }
355        Err(ErrorContext::new_missing(
356            "CounterAttrs",
357            "Bytes",
358            self.orig_loc,
359            self.buf.as_ptr() as usize,
360        ))
361    }
362    pub fn get_packets_old(&self) -> Result<u32, ErrorContext> {
363        let mut iter = self.clone();
364        iter.pos = 0;
365        for attr in iter {
366            if let CounterAttrs::PacketsOld(val) = attr? {
367                return Ok(val);
368            }
369        }
370        Err(ErrorContext::new_missing(
371            "CounterAttrs",
372            "PacketsOld",
373            self.orig_loc,
374            self.buf.as_ptr() as usize,
375        ))
376    }
377    pub fn get_bytes_old(&self) -> Result<u32, ErrorContext> {
378        let mut iter = self.clone();
379        iter.pos = 0;
380        for attr in iter {
381            if let CounterAttrs::BytesOld(val) = attr? {
382                return Ok(val);
383            }
384        }
385        Err(ErrorContext::new_missing(
386            "CounterAttrs",
387            "BytesOld",
388            self.orig_loc,
389            self.buf.as_ptr() as usize,
390        ))
391    }
392    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
393        let mut iter = self.clone();
394        iter.pos = 0;
395        for attr in iter {
396            if let CounterAttrs::Pad(val) = attr? {
397                return Ok(val);
398            }
399        }
400        Err(ErrorContext::new_missing(
401            "CounterAttrs",
402            "Pad",
403            self.orig_loc,
404            self.buf.as_ptr() as usize,
405        ))
406    }
407}
408impl CounterAttrs<'_> {
409    pub fn new<'a>(buf: &'a [u8]) -> IterableCounterAttrs<'a> {
410        IterableCounterAttrs::with_loc(buf, buf.as_ptr() as usize)
411    }
412    fn attr_from_type(r#type: u16) -> Option<&'static str> {
413        let res = match r#type {
414            1u16 => "Packets",
415            2u16 => "Bytes",
416            3u16 => "PacketsOld",
417            4u16 => "BytesOld",
418            5u16 => "Pad",
419            _ => return None,
420        };
421        Some(res)
422    }
423}
424#[derive(Clone, Copy, Default)]
425pub struct IterableCounterAttrs<'a> {
426    buf: &'a [u8],
427    pos: usize,
428    orig_loc: usize,
429}
430impl<'a> IterableCounterAttrs<'a> {
431    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
432        Self {
433            buf,
434            pos: 0,
435            orig_loc,
436        }
437    }
438    pub fn get_buf(&self) -> &'a [u8] {
439        self.buf
440    }
441}
442impl<'a> Iterator for IterableCounterAttrs<'a> {
443    type Item = Result<CounterAttrs<'a>, ErrorContext>;
444    fn next(&mut self) -> Option<Self::Item> {
445        let pos = self.pos;
446        let mut r#type;
447        loop {
448            r#type = None;
449            if self.buf.len() == self.pos {
450                return None;
451            }
452            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
453                break;
454            };
455            r#type = Some(header.r#type);
456            let res = match header.r#type {
457                1u16 => CounterAttrs::Packets({
458                    let res = parse_be_u64(next);
459                    let Some(val) = res else { break };
460                    val
461                }),
462                2u16 => CounterAttrs::Bytes({
463                    let res = parse_be_u64(next);
464                    let Some(val) = res else { break };
465                    val
466                }),
467                3u16 => CounterAttrs::PacketsOld({
468                    let res = parse_u32(next);
469                    let Some(val) = res else { break };
470                    val
471                }),
472                4u16 => CounterAttrs::BytesOld({
473                    let res = parse_u32(next);
474                    let Some(val) = res else { break };
475                    val
476                }),
477                5u16 => CounterAttrs::Pad({
478                    let res = Some(next);
479                    let Some(val) = res else { break };
480                    val
481                }),
482                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
483                n => continue,
484            };
485            return Some(Ok(res));
486        }
487        Some(Err(ErrorContext::new(
488            "CounterAttrs",
489            r#type.and_then(|t| CounterAttrs::attr_from_type(t)),
490            self.orig_loc,
491            self.buf.as_ptr().wrapping_add(pos) as usize,
492        )))
493    }
494}
495impl<'a> std::fmt::Debug for IterableCounterAttrs<'_> {
496    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
497        let mut fmt = f.debug_struct("CounterAttrs");
498        for attr in self.clone() {
499            let attr = match attr {
500                Ok(a) => a,
501                Err(err) => {
502                    fmt.finish()?;
503                    f.write_str("Err(")?;
504                    err.fmt(f)?;
505                    return f.write_str(")");
506                }
507            };
508            match attr {
509                CounterAttrs::Packets(val) => fmt.field("Packets", &val),
510                CounterAttrs::Bytes(val) => fmt.field("Bytes", &val),
511                CounterAttrs::PacketsOld(val) => fmt.field("PacketsOld", &val),
512                CounterAttrs::BytesOld(val) => fmt.field("BytesOld", &val),
513                CounterAttrs::Pad(val) => fmt.field("Pad", &val),
514            };
515        }
516        fmt.finish()
517    }
518}
519impl IterableCounterAttrs<'_> {
520    pub fn lookup_attr(
521        &self,
522        offset: usize,
523        missing_type: Option<u16>,
524    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
525        let mut stack = Vec::new();
526        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
527        if missing_type.is_some() && cur == offset {
528            stack.push(("CounterAttrs", offset));
529            return (
530                stack,
531                missing_type.and_then(|t| CounterAttrs::attr_from_type(t)),
532            );
533        }
534        if cur > offset || cur + self.buf.len() < offset {
535            return (stack, None);
536        }
537        let mut attrs = self.clone();
538        let mut last_off = cur + attrs.pos;
539        while let Some(attr) = attrs.next() {
540            let Ok(attr) = attr else { break };
541            match attr {
542                CounterAttrs::Packets(val) => {
543                    if last_off == offset {
544                        stack.push(("Packets", last_off));
545                        break;
546                    }
547                }
548                CounterAttrs::Bytes(val) => {
549                    if last_off == offset {
550                        stack.push(("Bytes", last_off));
551                        break;
552                    }
553                }
554                CounterAttrs::PacketsOld(val) => {
555                    if last_off == offset {
556                        stack.push(("PacketsOld", last_off));
557                        break;
558                    }
559                }
560                CounterAttrs::BytesOld(val) => {
561                    if last_off == offset {
562                        stack.push(("BytesOld", last_off));
563                        break;
564                    }
565                }
566                CounterAttrs::Pad(val) => {
567                    if last_off == offset {
568                        stack.push(("Pad", last_off));
569                        break;
570                    }
571                }
572                _ => {}
573            };
574            last_off = cur + attrs.pos;
575        }
576        if !stack.is_empty() {
577            stack.push(("CounterAttrs", cur));
578        }
579        (stack, None)
580    }
581}
582#[derive(Clone)]
583pub enum TupleProtoAttrs {
584    #[doc = "l4 protocol number"]
585    ProtoNum(u8),
586    #[doc = "l4 source port"]
587    ProtoSrcPort(u16),
588    #[doc = "l4 source port"]
589    ProtoDstPort(u16),
590    #[doc = "l4 icmp id"]
591    ProtoIcmpId(u16),
592    ProtoIcmpType(u8),
593    ProtoIcmpCode(u8),
594    #[doc = "l4 icmp id"]
595    ProtoIcmpv6Id(u16),
596    ProtoIcmpv6Type(u8),
597    ProtoIcmpv6Code(u8),
598}
599impl<'a> IterableTupleProtoAttrs<'a> {
600    #[doc = "l4 protocol number"]
601    pub fn get_proto_num(&self) -> Result<u8, ErrorContext> {
602        let mut iter = self.clone();
603        iter.pos = 0;
604        for attr in iter {
605            if let TupleProtoAttrs::ProtoNum(val) = attr? {
606                return Ok(val);
607            }
608        }
609        Err(ErrorContext::new_missing(
610            "TupleProtoAttrs",
611            "ProtoNum",
612            self.orig_loc,
613            self.buf.as_ptr() as usize,
614        ))
615    }
616    #[doc = "l4 source port"]
617    pub fn get_proto_src_port(&self) -> Result<u16, ErrorContext> {
618        let mut iter = self.clone();
619        iter.pos = 0;
620        for attr in iter {
621            if let TupleProtoAttrs::ProtoSrcPort(val) = attr? {
622                return Ok(val);
623            }
624        }
625        Err(ErrorContext::new_missing(
626            "TupleProtoAttrs",
627            "ProtoSrcPort",
628            self.orig_loc,
629            self.buf.as_ptr() as usize,
630        ))
631    }
632    #[doc = "l4 source port"]
633    pub fn get_proto_dst_port(&self) -> Result<u16, ErrorContext> {
634        let mut iter = self.clone();
635        iter.pos = 0;
636        for attr in iter {
637            if let TupleProtoAttrs::ProtoDstPort(val) = attr? {
638                return Ok(val);
639            }
640        }
641        Err(ErrorContext::new_missing(
642            "TupleProtoAttrs",
643            "ProtoDstPort",
644            self.orig_loc,
645            self.buf.as_ptr() as usize,
646        ))
647    }
648    #[doc = "l4 icmp id"]
649    pub fn get_proto_icmp_id(&self) -> Result<u16, ErrorContext> {
650        let mut iter = self.clone();
651        iter.pos = 0;
652        for attr in iter {
653            if let TupleProtoAttrs::ProtoIcmpId(val) = attr? {
654                return Ok(val);
655            }
656        }
657        Err(ErrorContext::new_missing(
658            "TupleProtoAttrs",
659            "ProtoIcmpId",
660            self.orig_loc,
661            self.buf.as_ptr() as usize,
662        ))
663    }
664    pub fn get_proto_icmp_type(&self) -> Result<u8, ErrorContext> {
665        let mut iter = self.clone();
666        iter.pos = 0;
667        for attr in iter {
668            if let TupleProtoAttrs::ProtoIcmpType(val) = attr? {
669                return Ok(val);
670            }
671        }
672        Err(ErrorContext::new_missing(
673            "TupleProtoAttrs",
674            "ProtoIcmpType",
675            self.orig_loc,
676            self.buf.as_ptr() as usize,
677        ))
678    }
679    pub fn get_proto_icmp_code(&self) -> Result<u8, ErrorContext> {
680        let mut iter = self.clone();
681        iter.pos = 0;
682        for attr in iter {
683            if let TupleProtoAttrs::ProtoIcmpCode(val) = attr? {
684                return Ok(val);
685            }
686        }
687        Err(ErrorContext::new_missing(
688            "TupleProtoAttrs",
689            "ProtoIcmpCode",
690            self.orig_loc,
691            self.buf.as_ptr() as usize,
692        ))
693    }
694    #[doc = "l4 icmp id"]
695    pub fn get_proto_icmpv6_id(&self) -> Result<u16, ErrorContext> {
696        let mut iter = self.clone();
697        iter.pos = 0;
698        for attr in iter {
699            if let TupleProtoAttrs::ProtoIcmpv6Id(val) = attr? {
700                return Ok(val);
701            }
702        }
703        Err(ErrorContext::new_missing(
704            "TupleProtoAttrs",
705            "ProtoIcmpv6Id",
706            self.orig_loc,
707            self.buf.as_ptr() as usize,
708        ))
709    }
710    pub fn get_proto_icmpv6_type(&self) -> Result<u8, ErrorContext> {
711        let mut iter = self.clone();
712        iter.pos = 0;
713        for attr in iter {
714            if let TupleProtoAttrs::ProtoIcmpv6Type(val) = attr? {
715                return Ok(val);
716            }
717        }
718        Err(ErrorContext::new_missing(
719            "TupleProtoAttrs",
720            "ProtoIcmpv6Type",
721            self.orig_loc,
722            self.buf.as_ptr() as usize,
723        ))
724    }
725    pub fn get_proto_icmpv6_code(&self) -> Result<u8, ErrorContext> {
726        let mut iter = self.clone();
727        iter.pos = 0;
728        for attr in iter {
729            if let TupleProtoAttrs::ProtoIcmpv6Code(val) = attr? {
730                return Ok(val);
731            }
732        }
733        Err(ErrorContext::new_missing(
734            "TupleProtoAttrs",
735            "ProtoIcmpv6Code",
736            self.orig_loc,
737            self.buf.as_ptr() as usize,
738        ))
739    }
740}
741impl TupleProtoAttrs {
742    pub fn new<'a>(buf: &'a [u8]) -> IterableTupleProtoAttrs<'a> {
743        IterableTupleProtoAttrs::with_loc(buf, buf.as_ptr() as usize)
744    }
745    fn attr_from_type(r#type: u16) -> Option<&'static str> {
746        let res = match r#type {
747            1u16 => "ProtoNum",
748            2u16 => "ProtoSrcPort",
749            3u16 => "ProtoDstPort",
750            4u16 => "ProtoIcmpId",
751            5u16 => "ProtoIcmpType",
752            6u16 => "ProtoIcmpCode",
753            7u16 => "ProtoIcmpv6Id",
754            8u16 => "ProtoIcmpv6Type",
755            9u16 => "ProtoIcmpv6Code",
756            _ => return None,
757        };
758        Some(res)
759    }
760}
761#[derive(Clone, Copy, Default)]
762pub struct IterableTupleProtoAttrs<'a> {
763    buf: &'a [u8],
764    pos: usize,
765    orig_loc: usize,
766}
767impl<'a> IterableTupleProtoAttrs<'a> {
768    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
769        Self {
770            buf,
771            pos: 0,
772            orig_loc,
773        }
774    }
775    pub fn get_buf(&self) -> &'a [u8] {
776        self.buf
777    }
778}
779impl<'a> Iterator for IterableTupleProtoAttrs<'a> {
780    type Item = Result<TupleProtoAttrs, ErrorContext>;
781    fn next(&mut self) -> Option<Self::Item> {
782        let pos = self.pos;
783        let mut r#type;
784        loop {
785            r#type = None;
786            if self.buf.len() == self.pos {
787                return None;
788            }
789            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
790                break;
791            };
792            r#type = Some(header.r#type);
793            let res = match header.r#type {
794                1u16 => TupleProtoAttrs::ProtoNum({
795                    let res = parse_u8(next);
796                    let Some(val) = res else { break };
797                    val
798                }),
799                2u16 => TupleProtoAttrs::ProtoSrcPort({
800                    let res = parse_be_u16(next);
801                    let Some(val) = res else { break };
802                    val
803                }),
804                3u16 => TupleProtoAttrs::ProtoDstPort({
805                    let res = parse_be_u16(next);
806                    let Some(val) = res else { break };
807                    val
808                }),
809                4u16 => TupleProtoAttrs::ProtoIcmpId({
810                    let res = parse_be_u16(next);
811                    let Some(val) = res else { break };
812                    val
813                }),
814                5u16 => TupleProtoAttrs::ProtoIcmpType({
815                    let res = parse_u8(next);
816                    let Some(val) = res else { break };
817                    val
818                }),
819                6u16 => TupleProtoAttrs::ProtoIcmpCode({
820                    let res = parse_u8(next);
821                    let Some(val) = res else { break };
822                    val
823                }),
824                7u16 => TupleProtoAttrs::ProtoIcmpv6Id({
825                    let res = parse_be_u16(next);
826                    let Some(val) = res else { break };
827                    val
828                }),
829                8u16 => TupleProtoAttrs::ProtoIcmpv6Type({
830                    let res = parse_u8(next);
831                    let Some(val) = res else { break };
832                    val
833                }),
834                9u16 => TupleProtoAttrs::ProtoIcmpv6Code({
835                    let res = parse_u8(next);
836                    let Some(val) = res else { break };
837                    val
838                }),
839                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
840                n => continue,
841            };
842            return Some(Ok(res));
843        }
844        Some(Err(ErrorContext::new(
845            "TupleProtoAttrs",
846            r#type.and_then(|t| TupleProtoAttrs::attr_from_type(t)),
847            self.orig_loc,
848            self.buf.as_ptr().wrapping_add(pos) as usize,
849        )))
850    }
851}
852impl std::fmt::Debug for IterableTupleProtoAttrs<'_> {
853    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
854        let mut fmt = f.debug_struct("TupleProtoAttrs");
855        for attr in self.clone() {
856            let attr = match attr {
857                Ok(a) => a,
858                Err(err) => {
859                    fmt.finish()?;
860                    f.write_str("Err(")?;
861                    err.fmt(f)?;
862                    return f.write_str(")");
863                }
864            };
865            match attr {
866                TupleProtoAttrs::ProtoNum(val) => fmt.field("ProtoNum", &val),
867                TupleProtoAttrs::ProtoSrcPort(val) => fmt.field("ProtoSrcPort", &val),
868                TupleProtoAttrs::ProtoDstPort(val) => fmt.field("ProtoDstPort", &val),
869                TupleProtoAttrs::ProtoIcmpId(val) => fmt.field("ProtoIcmpId", &val),
870                TupleProtoAttrs::ProtoIcmpType(val) => fmt.field("ProtoIcmpType", &val),
871                TupleProtoAttrs::ProtoIcmpCode(val) => fmt.field("ProtoIcmpCode", &val),
872                TupleProtoAttrs::ProtoIcmpv6Id(val) => fmt.field("ProtoIcmpv6Id", &val),
873                TupleProtoAttrs::ProtoIcmpv6Type(val) => fmt.field("ProtoIcmpv6Type", &val),
874                TupleProtoAttrs::ProtoIcmpv6Code(val) => fmt.field("ProtoIcmpv6Code", &val),
875            };
876        }
877        fmt.finish()
878    }
879}
880impl IterableTupleProtoAttrs<'_> {
881    pub fn lookup_attr(
882        &self,
883        offset: usize,
884        missing_type: Option<u16>,
885    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
886        let mut stack = Vec::new();
887        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
888        if missing_type.is_some() && cur == offset {
889            stack.push(("TupleProtoAttrs", offset));
890            return (
891                stack,
892                missing_type.and_then(|t| TupleProtoAttrs::attr_from_type(t)),
893            );
894        }
895        if cur > offset || cur + self.buf.len() < offset {
896            return (stack, None);
897        }
898        let mut attrs = self.clone();
899        let mut last_off = cur + attrs.pos;
900        while let Some(attr) = attrs.next() {
901            let Ok(attr) = attr else { break };
902            match attr {
903                TupleProtoAttrs::ProtoNum(val) => {
904                    if last_off == offset {
905                        stack.push(("ProtoNum", last_off));
906                        break;
907                    }
908                }
909                TupleProtoAttrs::ProtoSrcPort(val) => {
910                    if last_off == offset {
911                        stack.push(("ProtoSrcPort", last_off));
912                        break;
913                    }
914                }
915                TupleProtoAttrs::ProtoDstPort(val) => {
916                    if last_off == offset {
917                        stack.push(("ProtoDstPort", last_off));
918                        break;
919                    }
920                }
921                TupleProtoAttrs::ProtoIcmpId(val) => {
922                    if last_off == offset {
923                        stack.push(("ProtoIcmpId", last_off));
924                        break;
925                    }
926                }
927                TupleProtoAttrs::ProtoIcmpType(val) => {
928                    if last_off == offset {
929                        stack.push(("ProtoIcmpType", last_off));
930                        break;
931                    }
932                }
933                TupleProtoAttrs::ProtoIcmpCode(val) => {
934                    if last_off == offset {
935                        stack.push(("ProtoIcmpCode", last_off));
936                        break;
937                    }
938                }
939                TupleProtoAttrs::ProtoIcmpv6Id(val) => {
940                    if last_off == offset {
941                        stack.push(("ProtoIcmpv6Id", last_off));
942                        break;
943                    }
944                }
945                TupleProtoAttrs::ProtoIcmpv6Type(val) => {
946                    if last_off == offset {
947                        stack.push(("ProtoIcmpv6Type", last_off));
948                        break;
949                    }
950                }
951                TupleProtoAttrs::ProtoIcmpv6Code(val) => {
952                    if last_off == offset {
953                        stack.push(("ProtoIcmpv6Code", last_off));
954                        break;
955                    }
956                }
957                _ => {}
958            };
959            last_off = cur + attrs.pos;
960        }
961        if !stack.is_empty() {
962            stack.push(("TupleProtoAttrs", cur));
963        }
964        (stack, None)
965    }
966}
967#[derive(Clone)]
968pub enum TupleIpAttrs {
969    #[doc = "ipv4 source address"]
970    IpV4Src(std::net::Ipv4Addr),
971    #[doc = "ipv4 destination address"]
972    IpV4Dst(std::net::Ipv4Addr),
973    #[doc = "ipv6 source address"]
974    IpV6Src(std::net::Ipv6Addr),
975    #[doc = "ipv6 destination address"]
976    IpV6Dst(std::net::Ipv6Addr),
977}
978impl<'a> IterableTupleIpAttrs<'a> {
979    #[doc = "ipv4 source address"]
980    pub fn get_ip_v4_src(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
981        let mut iter = self.clone();
982        iter.pos = 0;
983        for attr in iter {
984            if let TupleIpAttrs::IpV4Src(val) = attr? {
985                return Ok(val);
986            }
987        }
988        Err(ErrorContext::new_missing(
989            "TupleIpAttrs",
990            "IpV4Src",
991            self.orig_loc,
992            self.buf.as_ptr() as usize,
993        ))
994    }
995    #[doc = "ipv4 destination address"]
996    pub fn get_ip_v4_dst(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
997        let mut iter = self.clone();
998        iter.pos = 0;
999        for attr in iter {
1000            if let TupleIpAttrs::IpV4Dst(val) = attr? {
1001                return Ok(val);
1002            }
1003        }
1004        Err(ErrorContext::new_missing(
1005            "TupleIpAttrs",
1006            "IpV4Dst",
1007            self.orig_loc,
1008            self.buf.as_ptr() as usize,
1009        ))
1010    }
1011    #[doc = "ipv6 source address"]
1012    pub fn get_ip_v6_src(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
1013        let mut iter = self.clone();
1014        iter.pos = 0;
1015        for attr in iter {
1016            if let TupleIpAttrs::IpV6Src(val) = attr? {
1017                return Ok(val);
1018            }
1019        }
1020        Err(ErrorContext::new_missing(
1021            "TupleIpAttrs",
1022            "IpV6Src",
1023            self.orig_loc,
1024            self.buf.as_ptr() as usize,
1025        ))
1026    }
1027    #[doc = "ipv6 destination address"]
1028    pub fn get_ip_v6_dst(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
1029        let mut iter = self.clone();
1030        iter.pos = 0;
1031        for attr in iter {
1032            if let TupleIpAttrs::IpV6Dst(val) = attr? {
1033                return Ok(val);
1034            }
1035        }
1036        Err(ErrorContext::new_missing(
1037            "TupleIpAttrs",
1038            "IpV6Dst",
1039            self.orig_loc,
1040            self.buf.as_ptr() as usize,
1041        ))
1042    }
1043}
1044impl TupleIpAttrs {
1045    pub fn new<'a>(buf: &'a [u8]) -> IterableTupleIpAttrs<'a> {
1046        IterableTupleIpAttrs::with_loc(buf, buf.as_ptr() as usize)
1047    }
1048    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1049        let res = match r#type {
1050            1u16 => "IpV4Src",
1051            2u16 => "IpV4Dst",
1052            3u16 => "IpV6Src",
1053            4u16 => "IpV6Dst",
1054            _ => return None,
1055        };
1056        Some(res)
1057    }
1058}
1059#[derive(Clone, Copy, Default)]
1060pub struct IterableTupleIpAttrs<'a> {
1061    buf: &'a [u8],
1062    pos: usize,
1063    orig_loc: usize,
1064}
1065impl<'a> IterableTupleIpAttrs<'a> {
1066    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1067        Self {
1068            buf,
1069            pos: 0,
1070            orig_loc,
1071        }
1072    }
1073    pub fn get_buf(&self) -> &'a [u8] {
1074        self.buf
1075    }
1076}
1077impl<'a> Iterator for IterableTupleIpAttrs<'a> {
1078    type Item = Result<TupleIpAttrs, ErrorContext>;
1079    fn next(&mut self) -> Option<Self::Item> {
1080        let pos = self.pos;
1081        let mut r#type;
1082        loop {
1083            r#type = None;
1084            if self.buf.len() == self.pos {
1085                return None;
1086            }
1087            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1088                break;
1089            };
1090            r#type = Some(header.r#type);
1091            let res = match header.r#type {
1092                1u16 => TupleIpAttrs::IpV4Src({
1093                    let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
1094                    let Some(val) = res else { break };
1095                    val
1096                }),
1097                2u16 => TupleIpAttrs::IpV4Dst({
1098                    let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
1099                    let Some(val) = res else { break };
1100                    val
1101                }),
1102                3u16 => TupleIpAttrs::IpV6Src({
1103                    let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
1104                    let Some(val) = res else { break };
1105                    val
1106                }),
1107                4u16 => TupleIpAttrs::IpV6Dst({
1108                    let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
1109                    let Some(val) = res else { break };
1110                    val
1111                }),
1112                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1113                n => continue,
1114            };
1115            return Some(Ok(res));
1116        }
1117        Some(Err(ErrorContext::new(
1118            "TupleIpAttrs",
1119            r#type.and_then(|t| TupleIpAttrs::attr_from_type(t)),
1120            self.orig_loc,
1121            self.buf.as_ptr().wrapping_add(pos) as usize,
1122        )))
1123    }
1124}
1125impl std::fmt::Debug for IterableTupleIpAttrs<'_> {
1126    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1127        let mut fmt = f.debug_struct("TupleIpAttrs");
1128        for attr in self.clone() {
1129            let attr = match attr {
1130                Ok(a) => a,
1131                Err(err) => {
1132                    fmt.finish()?;
1133                    f.write_str("Err(")?;
1134                    err.fmt(f)?;
1135                    return f.write_str(")");
1136                }
1137            };
1138            match attr {
1139                TupleIpAttrs::IpV4Src(val) => fmt.field("IpV4Src", &val),
1140                TupleIpAttrs::IpV4Dst(val) => fmt.field("IpV4Dst", &val),
1141                TupleIpAttrs::IpV6Src(val) => fmt.field("IpV6Src", &val),
1142                TupleIpAttrs::IpV6Dst(val) => fmt.field("IpV6Dst", &val),
1143            };
1144        }
1145        fmt.finish()
1146    }
1147}
1148impl IterableTupleIpAttrs<'_> {
1149    pub fn lookup_attr(
1150        &self,
1151        offset: usize,
1152        missing_type: Option<u16>,
1153    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1154        let mut stack = Vec::new();
1155        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1156        if missing_type.is_some() && cur == offset {
1157            stack.push(("TupleIpAttrs", offset));
1158            return (
1159                stack,
1160                missing_type.and_then(|t| TupleIpAttrs::attr_from_type(t)),
1161            );
1162        }
1163        if cur > offset || cur + self.buf.len() < offset {
1164            return (stack, None);
1165        }
1166        let mut attrs = self.clone();
1167        let mut last_off = cur + attrs.pos;
1168        while let Some(attr) = attrs.next() {
1169            let Ok(attr) = attr else { break };
1170            match attr {
1171                TupleIpAttrs::IpV4Src(val) => {
1172                    if last_off == offset {
1173                        stack.push(("IpV4Src", last_off));
1174                        break;
1175                    }
1176                }
1177                TupleIpAttrs::IpV4Dst(val) => {
1178                    if last_off == offset {
1179                        stack.push(("IpV4Dst", last_off));
1180                        break;
1181                    }
1182                }
1183                TupleIpAttrs::IpV6Src(val) => {
1184                    if last_off == offset {
1185                        stack.push(("IpV6Src", last_off));
1186                        break;
1187                    }
1188                }
1189                TupleIpAttrs::IpV6Dst(val) => {
1190                    if last_off == offset {
1191                        stack.push(("IpV6Dst", last_off));
1192                        break;
1193                    }
1194                }
1195                _ => {}
1196            };
1197            last_off = cur + attrs.pos;
1198        }
1199        if !stack.is_empty() {
1200            stack.push(("TupleIpAttrs", cur));
1201        }
1202        (stack, None)
1203    }
1204}
1205#[derive(Clone)]
1206pub enum TupleAttrs<'a> {
1207    #[doc = "conntrack l3 information"]
1208    TupleIp(IterableTupleIpAttrs<'a>),
1209    #[doc = "conntrack l4 information"]
1210    TupleProto(IterableTupleProtoAttrs<'a>),
1211    #[doc = "conntrack zone id"]
1212    TupleZone(u16),
1213}
1214impl<'a> IterableTupleAttrs<'a> {
1215    #[doc = "conntrack l3 information"]
1216    pub fn get_tuple_ip(&self) -> Result<IterableTupleIpAttrs<'a>, ErrorContext> {
1217        let mut iter = self.clone();
1218        iter.pos = 0;
1219        for attr in iter {
1220            if let TupleAttrs::TupleIp(val) = attr? {
1221                return Ok(val);
1222            }
1223        }
1224        Err(ErrorContext::new_missing(
1225            "TupleAttrs",
1226            "TupleIp",
1227            self.orig_loc,
1228            self.buf.as_ptr() as usize,
1229        ))
1230    }
1231    #[doc = "conntrack l4 information"]
1232    pub fn get_tuple_proto(&self) -> Result<IterableTupleProtoAttrs<'a>, ErrorContext> {
1233        let mut iter = self.clone();
1234        iter.pos = 0;
1235        for attr in iter {
1236            if let TupleAttrs::TupleProto(val) = attr? {
1237                return Ok(val);
1238            }
1239        }
1240        Err(ErrorContext::new_missing(
1241            "TupleAttrs",
1242            "TupleProto",
1243            self.orig_loc,
1244            self.buf.as_ptr() as usize,
1245        ))
1246    }
1247    #[doc = "conntrack zone id"]
1248    pub fn get_tuple_zone(&self) -> Result<u16, ErrorContext> {
1249        let mut iter = self.clone();
1250        iter.pos = 0;
1251        for attr in iter {
1252            if let TupleAttrs::TupleZone(val) = attr? {
1253                return Ok(val);
1254            }
1255        }
1256        Err(ErrorContext::new_missing(
1257            "TupleAttrs",
1258            "TupleZone",
1259            self.orig_loc,
1260            self.buf.as_ptr() as usize,
1261        ))
1262    }
1263}
1264impl TupleAttrs<'_> {
1265    pub fn new<'a>(buf: &'a [u8]) -> IterableTupleAttrs<'a> {
1266        IterableTupleAttrs::with_loc(buf, buf.as_ptr() as usize)
1267    }
1268    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1269        let res = match r#type {
1270            1u16 => "TupleIp",
1271            2u16 => "TupleProto",
1272            3u16 => "TupleZone",
1273            _ => return None,
1274        };
1275        Some(res)
1276    }
1277}
1278#[derive(Clone, Copy, Default)]
1279pub struct IterableTupleAttrs<'a> {
1280    buf: &'a [u8],
1281    pos: usize,
1282    orig_loc: usize,
1283}
1284impl<'a> IterableTupleAttrs<'a> {
1285    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1286        Self {
1287            buf,
1288            pos: 0,
1289            orig_loc,
1290        }
1291    }
1292    pub fn get_buf(&self) -> &'a [u8] {
1293        self.buf
1294    }
1295}
1296impl<'a> Iterator for IterableTupleAttrs<'a> {
1297    type Item = Result<TupleAttrs<'a>, ErrorContext>;
1298    fn next(&mut self) -> Option<Self::Item> {
1299        let pos = self.pos;
1300        let mut r#type;
1301        loop {
1302            r#type = None;
1303            if self.buf.len() == self.pos {
1304                return None;
1305            }
1306            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1307                break;
1308            };
1309            r#type = Some(header.r#type);
1310            let res = match header.r#type {
1311                1u16 => TupleAttrs::TupleIp({
1312                    let res = Some(IterableTupleIpAttrs::with_loc(next, self.orig_loc));
1313                    let Some(val) = res else { break };
1314                    val
1315                }),
1316                2u16 => TupleAttrs::TupleProto({
1317                    let res = Some(IterableTupleProtoAttrs::with_loc(next, self.orig_loc));
1318                    let Some(val) = res else { break };
1319                    val
1320                }),
1321                3u16 => TupleAttrs::TupleZone({
1322                    let res = parse_be_u16(next);
1323                    let Some(val) = res else { break };
1324                    val
1325                }),
1326                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1327                n => continue,
1328            };
1329            return Some(Ok(res));
1330        }
1331        Some(Err(ErrorContext::new(
1332            "TupleAttrs",
1333            r#type.and_then(|t| TupleAttrs::attr_from_type(t)),
1334            self.orig_loc,
1335            self.buf.as_ptr().wrapping_add(pos) as usize,
1336        )))
1337    }
1338}
1339impl<'a> std::fmt::Debug for IterableTupleAttrs<'_> {
1340    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1341        let mut fmt = f.debug_struct("TupleAttrs");
1342        for attr in self.clone() {
1343            let attr = match attr {
1344                Ok(a) => a,
1345                Err(err) => {
1346                    fmt.finish()?;
1347                    f.write_str("Err(")?;
1348                    err.fmt(f)?;
1349                    return f.write_str(")");
1350                }
1351            };
1352            match attr {
1353                TupleAttrs::TupleIp(val) => fmt.field("TupleIp", &val),
1354                TupleAttrs::TupleProto(val) => fmt.field("TupleProto", &val),
1355                TupleAttrs::TupleZone(val) => fmt.field("TupleZone", &val),
1356            };
1357        }
1358        fmt.finish()
1359    }
1360}
1361impl IterableTupleAttrs<'_> {
1362    pub fn lookup_attr(
1363        &self,
1364        offset: usize,
1365        missing_type: Option<u16>,
1366    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1367        let mut stack = Vec::new();
1368        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1369        if missing_type.is_some() && cur == offset {
1370            stack.push(("TupleAttrs", offset));
1371            return (
1372                stack,
1373                missing_type.and_then(|t| TupleAttrs::attr_from_type(t)),
1374            );
1375        }
1376        if cur > offset || cur + self.buf.len() < offset {
1377            return (stack, None);
1378        }
1379        let mut attrs = self.clone();
1380        let mut last_off = cur + attrs.pos;
1381        let mut missing = None;
1382        while let Some(attr) = attrs.next() {
1383            let Ok(attr) = attr else { break };
1384            match attr {
1385                TupleAttrs::TupleIp(val) => {
1386                    (stack, missing) = val.lookup_attr(offset, missing_type);
1387                    if !stack.is_empty() {
1388                        break;
1389                    }
1390                }
1391                TupleAttrs::TupleProto(val) => {
1392                    (stack, missing) = val.lookup_attr(offset, missing_type);
1393                    if !stack.is_empty() {
1394                        break;
1395                    }
1396                }
1397                TupleAttrs::TupleZone(val) => {
1398                    if last_off == offset {
1399                        stack.push(("TupleZone", last_off));
1400                        break;
1401                    }
1402                }
1403                _ => {}
1404            };
1405            last_off = cur + attrs.pos;
1406        }
1407        if !stack.is_empty() {
1408            stack.push(("TupleAttrs", cur));
1409        }
1410        (stack, missing)
1411    }
1412}
1413#[derive(Clone)]
1414pub enum ProtoinfoTcpAttrs {
1415    #[doc = "tcp connection state\nAssociated type: [`NfCtTcpState`] (enum)"]
1416    TcpState(u8),
1417    #[doc = "window scaling factor in original direction"]
1418    TcpWscaleOriginal(u8),
1419    #[doc = "window scaling factor in reply direction"]
1420    TcpWscaleReply(u8),
1421    TcpFlagsOriginal(NfCtTcpFlagsMask),
1422    TcpFlagsReply(NfCtTcpFlagsMask),
1423}
1424impl<'a> IterableProtoinfoTcpAttrs<'a> {
1425    #[doc = "tcp connection state\nAssociated type: [`NfCtTcpState`] (enum)"]
1426    pub fn get_tcp_state(&self) -> Result<u8, ErrorContext> {
1427        let mut iter = self.clone();
1428        iter.pos = 0;
1429        for attr in iter {
1430            if let ProtoinfoTcpAttrs::TcpState(val) = attr? {
1431                return Ok(val);
1432            }
1433        }
1434        Err(ErrorContext::new_missing(
1435            "ProtoinfoTcpAttrs",
1436            "TcpState",
1437            self.orig_loc,
1438            self.buf.as_ptr() as usize,
1439        ))
1440    }
1441    #[doc = "window scaling factor in original direction"]
1442    pub fn get_tcp_wscale_original(&self) -> Result<u8, ErrorContext> {
1443        let mut iter = self.clone();
1444        iter.pos = 0;
1445        for attr in iter {
1446            if let ProtoinfoTcpAttrs::TcpWscaleOriginal(val) = attr? {
1447                return Ok(val);
1448            }
1449        }
1450        Err(ErrorContext::new_missing(
1451            "ProtoinfoTcpAttrs",
1452            "TcpWscaleOriginal",
1453            self.orig_loc,
1454            self.buf.as_ptr() as usize,
1455        ))
1456    }
1457    #[doc = "window scaling factor in reply direction"]
1458    pub fn get_tcp_wscale_reply(&self) -> Result<u8, ErrorContext> {
1459        let mut iter = self.clone();
1460        iter.pos = 0;
1461        for attr in iter {
1462            if let ProtoinfoTcpAttrs::TcpWscaleReply(val) = attr? {
1463                return Ok(val);
1464            }
1465        }
1466        Err(ErrorContext::new_missing(
1467            "ProtoinfoTcpAttrs",
1468            "TcpWscaleReply",
1469            self.orig_loc,
1470            self.buf.as_ptr() as usize,
1471        ))
1472    }
1473    pub fn get_tcp_flags_original(&self) -> Result<NfCtTcpFlagsMask, ErrorContext> {
1474        let mut iter = self.clone();
1475        iter.pos = 0;
1476        for attr in iter {
1477            if let ProtoinfoTcpAttrs::TcpFlagsOriginal(val) = attr? {
1478                return Ok(val);
1479            }
1480        }
1481        Err(ErrorContext::new_missing(
1482            "ProtoinfoTcpAttrs",
1483            "TcpFlagsOriginal",
1484            self.orig_loc,
1485            self.buf.as_ptr() as usize,
1486        ))
1487    }
1488    pub fn get_tcp_flags_reply(&self) -> Result<NfCtTcpFlagsMask, ErrorContext> {
1489        let mut iter = self.clone();
1490        iter.pos = 0;
1491        for attr in iter {
1492            if let ProtoinfoTcpAttrs::TcpFlagsReply(val) = attr? {
1493                return Ok(val);
1494            }
1495        }
1496        Err(ErrorContext::new_missing(
1497            "ProtoinfoTcpAttrs",
1498            "TcpFlagsReply",
1499            self.orig_loc,
1500            self.buf.as_ptr() as usize,
1501        ))
1502    }
1503}
1504impl ProtoinfoTcpAttrs {
1505    pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoTcpAttrs<'a> {
1506        IterableProtoinfoTcpAttrs::with_loc(buf, buf.as_ptr() as usize)
1507    }
1508    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1509        let res = match r#type {
1510            1u16 => "TcpState",
1511            2u16 => "TcpWscaleOriginal",
1512            3u16 => "TcpWscaleReply",
1513            4u16 => "TcpFlagsOriginal",
1514            5u16 => "TcpFlagsReply",
1515            _ => return None,
1516        };
1517        Some(res)
1518    }
1519}
1520#[derive(Clone, Copy, Default)]
1521pub struct IterableProtoinfoTcpAttrs<'a> {
1522    buf: &'a [u8],
1523    pos: usize,
1524    orig_loc: usize,
1525}
1526impl<'a> IterableProtoinfoTcpAttrs<'a> {
1527    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1528        Self {
1529            buf,
1530            pos: 0,
1531            orig_loc,
1532        }
1533    }
1534    pub fn get_buf(&self) -> &'a [u8] {
1535        self.buf
1536    }
1537}
1538impl<'a> Iterator for IterableProtoinfoTcpAttrs<'a> {
1539    type Item = Result<ProtoinfoTcpAttrs, ErrorContext>;
1540    fn next(&mut self) -> Option<Self::Item> {
1541        let pos = self.pos;
1542        let mut r#type;
1543        loop {
1544            r#type = None;
1545            if self.buf.len() == self.pos {
1546                return None;
1547            }
1548            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1549                break;
1550            };
1551            r#type = Some(header.r#type);
1552            let res = match header.r#type {
1553                1u16 => ProtoinfoTcpAttrs::TcpState({
1554                    let res = parse_u8(next);
1555                    let Some(val) = res else { break };
1556                    val
1557                }),
1558                2u16 => ProtoinfoTcpAttrs::TcpWscaleOriginal({
1559                    let res = parse_u8(next);
1560                    let Some(val) = res else { break };
1561                    val
1562                }),
1563                3u16 => ProtoinfoTcpAttrs::TcpWscaleReply({
1564                    let res = parse_u8(next);
1565                    let Some(val) = res else { break };
1566                    val
1567                }),
1568                4u16 => ProtoinfoTcpAttrs::TcpFlagsOriginal({
1569                    let res = Some(NfCtTcpFlagsMask::new_from_zeroed(next));
1570                    let Some(val) = res else { break };
1571                    val
1572                }),
1573                5u16 => ProtoinfoTcpAttrs::TcpFlagsReply({
1574                    let res = Some(NfCtTcpFlagsMask::new_from_zeroed(next));
1575                    let Some(val) = res else { break };
1576                    val
1577                }),
1578                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1579                n => continue,
1580            };
1581            return Some(Ok(res));
1582        }
1583        Some(Err(ErrorContext::new(
1584            "ProtoinfoTcpAttrs",
1585            r#type.and_then(|t| ProtoinfoTcpAttrs::attr_from_type(t)),
1586            self.orig_loc,
1587            self.buf.as_ptr().wrapping_add(pos) as usize,
1588        )))
1589    }
1590}
1591impl std::fmt::Debug for IterableProtoinfoTcpAttrs<'_> {
1592    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1593        let mut fmt = f.debug_struct("ProtoinfoTcpAttrs");
1594        for attr in self.clone() {
1595            let attr = match attr {
1596                Ok(a) => a,
1597                Err(err) => {
1598                    fmt.finish()?;
1599                    f.write_str("Err(")?;
1600                    err.fmt(f)?;
1601                    return f.write_str(")");
1602                }
1603            };
1604            match attr {
1605                ProtoinfoTcpAttrs::TcpState(val) => fmt.field(
1606                    "TcpState",
1607                    &FormatEnum(val.into(), NfCtTcpState::from_value),
1608                ),
1609                ProtoinfoTcpAttrs::TcpWscaleOriginal(val) => fmt.field("TcpWscaleOriginal", &val),
1610                ProtoinfoTcpAttrs::TcpWscaleReply(val) => fmt.field("TcpWscaleReply", &val),
1611                ProtoinfoTcpAttrs::TcpFlagsOriginal(val) => fmt.field("TcpFlagsOriginal", &val),
1612                ProtoinfoTcpAttrs::TcpFlagsReply(val) => fmt.field("TcpFlagsReply", &val),
1613            };
1614        }
1615        fmt.finish()
1616    }
1617}
1618impl IterableProtoinfoTcpAttrs<'_> {
1619    pub fn lookup_attr(
1620        &self,
1621        offset: usize,
1622        missing_type: Option<u16>,
1623    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1624        let mut stack = Vec::new();
1625        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1626        if missing_type.is_some() && cur == offset {
1627            stack.push(("ProtoinfoTcpAttrs", offset));
1628            return (
1629                stack,
1630                missing_type.and_then(|t| ProtoinfoTcpAttrs::attr_from_type(t)),
1631            );
1632        }
1633        if cur > offset || cur + self.buf.len() < offset {
1634            return (stack, None);
1635        }
1636        let mut attrs = self.clone();
1637        let mut last_off = cur + attrs.pos;
1638        while let Some(attr) = attrs.next() {
1639            let Ok(attr) = attr else { break };
1640            match attr {
1641                ProtoinfoTcpAttrs::TcpState(val) => {
1642                    if last_off == offset {
1643                        stack.push(("TcpState", last_off));
1644                        break;
1645                    }
1646                }
1647                ProtoinfoTcpAttrs::TcpWscaleOriginal(val) => {
1648                    if last_off == offset {
1649                        stack.push(("TcpWscaleOriginal", last_off));
1650                        break;
1651                    }
1652                }
1653                ProtoinfoTcpAttrs::TcpWscaleReply(val) => {
1654                    if last_off == offset {
1655                        stack.push(("TcpWscaleReply", last_off));
1656                        break;
1657                    }
1658                }
1659                ProtoinfoTcpAttrs::TcpFlagsOriginal(val) => {
1660                    if last_off == offset {
1661                        stack.push(("TcpFlagsOriginal", last_off));
1662                        break;
1663                    }
1664                }
1665                ProtoinfoTcpAttrs::TcpFlagsReply(val) => {
1666                    if last_off == offset {
1667                        stack.push(("TcpFlagsReply", last_off));
1668                        break;
1669                    }
1670                }
1671                _ => {}
1672            };
1673            last_off = cur + attrs.pos;
1674        }
1675        if !stack.is_empty() {
1676            stack.push(("ProtoinfoTcpAttrs", cur));
1677        }
1678        (stack, None)
1679    }
1680}
1681#[derive(Clone)]
1682pub enum ProtoinfoDccpAttrs<'a> {
1683    #[doc = "dccp connection state"]
1684    DccpState(u8),
1685    DccpRole(u8),
1686    DccpHandshakeSeq(u64),
1687    DccpPad(&'a [u8]),
1688}
1689impl<'a> IterableProtoinfoDccpAttrs<'a> {
1690    #[doc = "dccp connection state"]
1691    pub fn get_dccp_state(&self) -> Result<u8, ErrorContext> {
1692        let mut iter = self.clone();
1693        iter.pos = 0;
1694        for attr in iter {
1695            if let ProtoinfoDccpAttrs::DccpState(val) = attr? {
1696                return Ok(val);
1697            }
1698        }
1699        Err(ErrorContext::new_missing(
1700            "ProtoinfoDccpAttrs",
1701            "DccpState",
1702            self.orig_loc,
1703            self.buf.as_ptr() as usize,
1704        ))
1705    }
1706    pub fn get_dccp_role(&self) -> Result<u8, ErrorContext> {
1707        let mut iter = self.clone();
1708        iter.pos = 0;
1709        for attr in iter {
1710            if let ProtoinfoDccpAttrs::DccpRole(val) = attr? {
1711                return Ok(val);
1712            }
1713        }
1714        Err(ErrorContext::new_missing(
1715            "ProtoinfoDccpAttrs",
1716            "DccpRole",
1717            self.orig_loc,
1718            self.buf.as_ptr() as usize,
1719        ))
1720    }
1721    pub fn get_dccp_handshake_seq(&self) -> Result<u64, ErrorContext> {
1722        let mut iter = self.clone();
1723        iter.pos = 0;
1724        for attr in iter {
1725            if let ProtoinfoDccpAttrs::DccpHandshakeSeq(val) = attr? {
1726                return Ok(val);
1727            }
1728        }
1729        Err(ErrorContext::new_missing(
1730            "ProtoinfoDccpAttrs",
1731            "DccpHandshakeSeq",
1732            self.orig_loc,
1733            self.buf.as_ptr() as usize,
1734        ))
1735    }
1736    pub fn get_dccp_pad(&self) -> Result<&'a [u8], ErrorContext> {
1737        let mut iter = self.clone();
1738        iter.pos = 0;
1739        for attr in iter {
1740            if let ProtoinfoDccpAttrs::DccpPad(val) = attr? {
1741                return Ok(val);
1742            }
1743        }
1744        Err(ErrorContext::new_missing(
1745            "ProtoinfoDccpAttrs",
1746            "DccpPad",
1747            self.orig_loc,
1748            self.buf.as_ptr() as usize,
1749        ))
1750    }
1751}
1752impl ProtoinfoDccpAttrs<'_> {
1753    pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoDccpAttrs<'a> {
1754        IterableProtoinfoDccpAttrs::with_loc(buf, buf.as_ptr() as usize)
1755    }
1756    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1757        let res = match r#type {
1758            1u16 => "DccpState",
1759            2u16 => "DccpRole",
1760            3u16 => "DccpHandshakeSeq",
1761            4u16 => "DccpPad",
1762            _ => return None,
1763        };
1764        Some(res)
1765    }
1766}
1767#[derive(Clone, Copy, Default)]
1768pub struct IterableProtoinfoDccpAttrs<'a> {
1769    buf: &'a [u8],
1770    pos: usize,
1771    orig_loc: usize,
1772}
1773impl<'a> IterableProtoinfoDccpAttrs<'a> {
1774    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1775        Self {
1776            buf,
1777            pos: 0,
1778            orig_loc,
1779        }
1780    }
1781    pub fn get_buf(&self) -> &'a [u8] {
1782        self.buf
1783    }
1784}
1785impl<'a> Iterator for IterableProtoinfoDccpAttrs<'a> {
1786    type Item = Result<ProtoinfoDccpAttrs<'a>, ErrorContext>;
1787    fn next(&mut self) -> Option<Self::Item> {
1788        let pos = self.pos;
1789        let mut r#type;
1790        loop {
1791            r#type = None;
1792            if self.buf.len() == self.pos {
1793                return None;
1794            }
1795            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1796                break;
1797            };
1798            r#type = Some(header.r#type);
1799            let res = match header.r#type {
1800                1u16 => ProtoinfoDccpAttrs::DccpState({
1801                    let res = parse_u8(next);
1802                    let Some(val) = res else { break };
1803                    val
1804                }),
1805                2u16 => ProtoinfoDccpAttrs::DccpRole({
1806                    let res = parse_u8(next);
1807                    let Some(val) = res else { break };
1808                    val
1809                }),
1810                3u16 => ProtoinfoDccpAttrs::DccpHandshakeSeq({
1811                    let res = parse_be_u64(next);
1812                    let Some(val) = res else { break };
1813                    val
1814                }),
1815                4u16 => ProtoinfoDccpAttrs::DccpPad({
1816                    let res = Some(next);
1817                    let Some(val) = res else { break };
1818                    val
1819                }),
1820                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1821                n => continue,
1822            };
1823            return Some(Ok(res));
1824        }
1825        Some(Err(ErrorContext::new(
1826            "ProtoinfoDccpAttrs",
1827            r#type.and_then(|t| ProtoinfoDccpAttrs::attr_from_type(t)),
1828            self.orig_loc,
1829            self.buf.as_ptr().wrapping_add(pos) as usize,
1830        )))
1831    }
1832}
1833impl<'a> std::fmt::Debug for IterableProtoinfoDccpAttrs<'_> {
1834    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1835        let mut fmt = f.debug_struct("ProtoinfoDccpAttrs");
1836        for attr in self.clone() {
1837            let attr = match attr {
1838                Ok(a) => a,
1839                Err(err) => {
1840                    fmt.finish()?;
1841                    f.write_str("Err(")?;
1842                    err.fmt(f)?;
1843                    return f.write_str(")");
1844                }
1845            };
1846            match attr {
1847                ProtoinfoDccpAttrs::DccpState(val) => fmt.field("DccpState", &val),
1848                ProtoinfoDccpAttrs::DccpRole(val) => fmt.field("DccpRole", &val),
1849                ProtoinfoDccpAttrs::DccpHandshakeSeq(val) => fmt.field("DccpHandshakeSeq", &val),
1850                ProtoinfoDccpAttrs::DccpPad(val) => fmt.field("DccpPad", &val),
1851            };
1852        }
1853        fmt.finish()
1854    }
1855}
1856impl IterableProtoinfoDccpAttrs<'_> {
1857    pub fn lookup_attr(
1858        &self,
1859        offset: usize,
1860        missing_type: Option<u16>,
1861    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1862        let mut stack = Vec::new();
1863        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1864        if missing_type.is_some() && cur == offset {
1865            stack.push(("ProtoinfoDccpAttrs", offset));
1866            return (
1867                stack,
1868                missing_type.and_then(|t| ProtoinfoDccpAttrs::attr_from_type(t)),
1869            );
1870        }
1871        if cur > offset || cur + self.buf.len() < offset {
1872            return (stack, None);
1873        }
1874        let mut attrs = self.clone();
1875        let mut last_off = cur + attrs.pos;
1876        while let Some(attr) = attrs.next() {
1877            let Ok(attr) = attr else { break };
1878            match attr {
1879                ProtoinfoDccpAttrs::DccpState(val) => {
1880                    if last_off == offset {
1881                        stack.push(("DccpState", last_off));
1882                        break;
1883                    }
1884                }
1885                ProtoinfoDccpAttrs::DccpRole(val) => {
1886                    if last_off == offset {
1887                        stack.push(("DccpRole", last_off));
1888                        break;
1889                    }
1890                }
1891                ProtoinfoDccpAttrs::DccpHandshakeSeq(val) => {
1892                    if last_off == offset {
1893                        stack.push(("DccpHandshakeSeq", last_off));
1894                        break;
1895                    }
1896                }
1897                ProtoinfoDccpAttrs::DccpPad(val) => {
1898                    if last_off == offset {
1899                        stack.push(("DccpPad", last_off));
1900                        break;
1901                    }
1902                }
1903                _ => {}
1904            };
1905            last_off = cur + attrs.pos;
1906        }
1907        if !stack.is_empty() {
1908            stack.push(("ProtoinfoDccpAttrs", cur));
1909        }
1910        (stack, None)
1911    }
1912}
1913#[derive(Clone)]
1914pub enum ProtoinfoSctpAttrs {
1915    #[doc = "sctp connection state\nAssociated type: [`NfCtSctpState`] (enum)"]
1916    SctpState(u8),
1917    VtagOriginal(u32),
1918    VtagReply(u32),
1919}
1920impl<'a> IterableProtoinfoSctpAttrs<'a> {
1921    #[doc = "sctp connection state\nAssociated type: [`NfCtSctpState`] (enum)"]
1922    pub fn get_sctp_state(&self) -> Result<u8, ErrorContext> {
1923        let mut iter = self.clone();
1924        iter.pos = 0;
1925        for attr in iter {
1926            if let ProtoinfoSctpAttrs::SctpState(val) = attr? {
1927                return Ok(val);
1928            }
1929        }
1930        Err(ErrorContext::new_missing(
1931            "ProtoinfoSctpAttrs",
1932            "SctpState",
1933            self.orig_loc,
1934            self.buf.as_ptr() as usize,
1935        ))
1936    }
1937    pub fn get_vtag_original(&self) -> Result<u32, ErrorContext> {
1938        let mut iter = self.clone();
1939        iter.pos = 0;
1940        for attr in iter {
1941            if let ProtoinfoSctpAttrs::VtagOriginal(val) = attr? {
1942                return Ok(val);
1943            }
1944        }
1945        Err(ErrorContext::new_missing(
1946            "ProtoinfoSctpAttrs",
1947            "VtagOriginal",
1948            self.orig_loc,
1949            self.buf.as_ptr() as usize,
1950        ))
1951    }
1952    pub fn get_vtag_reply(&self) -> Result<u32, ErrorContext> {
1953        let mut iter = self.clone();
1954        iter.pos = 0;
1955        for attr in iter {
1956            if let ProtoinfoSctpAttrs::VtagReply(val) = attr? {
1957                return Ok(val);
1958            }
1959        }
1960        Err(ErrorContext::new_missing(
1961            "ProtoinfoSctpAttrs",
1962            "VtagReply",
1963            self.orig_loc,
1964            self.buf.as_ptr() as usize,
1965        ))
1966    }
1967}
1968impl ProtoinfoSctpAttrs {
1969    pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoSctpAttrs<'a> {
1970        IterableProtoinfoSctpAttrs::with_loc(buf, buf.as_ptr() as usize)
1971    }
1972    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1973        let res = match r#type {
1974            1u16 => "SctpState",
1975            2u16 => "VtagOriginal",
1976            3u16 => "VtagReply",
1977            _ => return None,
1978        };
1979        Some(res)
1980    }
1981}
1982#[derive(Clone, Copy, Default)]
1983pub struct IterableProtoinfoSctpAttrs<'a> {
1984    buf: &'a [u8],
1985    pos: usize,
1986    orig_loc: usize,
1987}
1988impl<'a> IterableProtoinfoSctpAttrs<'a> {
1989    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1990        Self {
1991            buf,
1992            pos: 0,
1993            orig_loc,
1994        }
1995    }
1996    pub fn get_buf(&self) -> &'a [u8] {
1997        self.buf
1998    }
1999}
2000impl<'a> Iterator for IterableProtoinfoSctpAttrs<'a> {
2001    type Item = Result<ProtoinfoSctpAttrs, ErrorContext>;
2002    fn next(&mut self) -> Option<Self::Item> {
2003        let pos = self.pos;
2004        let mut r#type;
2005        loop {
2006            r#type = None;
2007            if self.buf.len() == self.pos {
2008                return None;
2009            }
2010            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2011                break;
2012            };
2013            r#type = Some(header.r#type);
2014            let res = match header.r#type {
2015                1u16 => ProtoinfoSctpAttrs::SctpState({
2016                    let res = parse_u8(next);
2017                    let Some(val) = res else { break };
2018                    val
2019                }),
2020                2u16 => ProtoinfoSctpAttrs::VtagOriginal({
2021                    let res = parse_be_u32(next);
2022                    let Some(val) = res else { break };
2023                    val
2024                }),
2025                3u16 => ProtoinfoSctpAttrs::VtagReply({
2026                    let res = parse_be_u32(next);
2027                    let Some(val) = res else { break };
2028                    val
2029                }),
2030                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2031                n => continue,
2032            };
2033            return Some(Ok(res));
2034        }
2035        Some(Err(ErrorContext::new(
2036            "ProtoinfoSctpAttrs",
2037            r#type.and_then(|t| ProtoinfoSctpAttrs::attr_from_type(t)),
2038            self.orig_loc,
2039            self.buf.as_ptr().wrapping_add(pos) as usize,
2040        )))
2041    }
2042}
2043impl std::fmt::Debug for IterableProtoinfoSctpAttrs<'_> {
2044    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2045        let mut fmt = f.debug_struct("ProtoinfoSctpAttrs");
2046        for attr in self.clone() {
2047            let attr = match attr {
2048                Ok(a) => a,
2049                Err(err) => {
2050                    fmt.finish()?;
2051                    f.write_str("Err(")?;
2052                    err.fmt(f)?;
2053                    return f.write_str(")");
2054                }
2055            };
2056            match attr {
2057                ProtoinfoSctpAttrs::SctpState(val) => fmt.field(
2058                    "SctpState",
2059                    &FormatEnum(val.into(), NfCtSctpState::from_value),
2060                ),
2061                ProtoinfoSctpAttrs::VtagOriginal(val) => fmt.field("VtagOriginal", &val),
2062                ProtoinfoSctpAttrs::VtagReply(val) => fmt.field("VtagReply", &val),
2063            };
2064        }
2065        fmt.finish()
2066    }
2067}
2068impl IterableProtoinfoSctpAttrs<'_> {
2069    pub fn lookup_attr(
2070        &self,
2071        offset: usize,
2072        missing_type: Option<u16>,
2073    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2074        let mut stack = Vec::new();
2075        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2076        if missing_type.is_some() && cur == offset {
2077            stack.push(("ProtoinfoSctpAttrs", offset));
2078            return (
2079                stack,
2080                missing_type.and_then(|t| ProtoinfoSctpAttrs::attr_from_type(t)),
2081            );
2082        }
2083        if cur > offset || cur + self.buf.len() < offset {
2084            return (stack, None);
2085        }
2086        let mut attrs = self.clone();
2087        let mut last_off = cur + attrs.pos;
2088        while let Some(attr) = attrs.next() {
2089            let Ok(attr) = attr else { break };
2090            match attr {
2091                ProtoinfoSctpAttrs::SctpState(val) => {
2092                    if last_off == offset {
2093                        stack.push(("SctpState", last_off));
2094                        break;
2095                    }
2096                }
2097                ProtoinfoSctpAttrs::VtagOriginal(val) => {
2098                    if last_off == offset {
2099                        stack.push(("VtagOriginal", last_off));
2100                        break;
2101                    }
2102                }
2103                ProtoinfoSctpAttrs::VtagReply(val) => {
2104                    if last_off == offset {
2105                        stack.push(("VtagReply", last_off));
2106                        break;
2107                    }
2108                }
2109                _ => {}
2110            };
2111            last_off = cur + attrs.pos;
2112        }
2113        if !stack.is_empty() {
2114            stack.push(("ProtoinfoSctpAttrs", cur));
2115        }
2116        (stack, None)
2117    }
2118}
2119#[derive(Clone)]
2120pub enum ProtoinfoAttrs<'a> {
2121    #[doc = "conntrack tcp state information"]
2122    ProtoinfoTcp(IterableProtoinfoTcpAttrs<'a>),
2123    #[doc = "conntrack dccp state information"]
2124    ProtoinfoDccp(IterableProtoinfoDccpAttrs<'a>),
2125    #[doc = "conntrack sctp state information"]
2126    ProtoinfoSctp(IterableProtoinfoSctpAttrs<'a>),
2127}
2128impl<'a> IterableProtoinfoAttrs<'a> {
2129    #[doc = "conntrack tcp state information"]
2130    pub fn get_protoinfo_tcp(&self) -> Result<IterableProtoinfoTcpAttrs<'a>, ErrorContext> {
2131        let mut iter = self.clone();
2132        iter.pos = 0;
2133        for attr in iter {
2134            if let ProtoinfoAttrs::ProtoinfoTcp(val) = attr? {
2135                return Ok(val);
2136            }
2137        }
2138        Err(ErrorContext::new_missing(
2139            "ProtoinfoAttrs",
2140            "ProtoinfoTcp",
2141            self.orig_loc,
2142            self.buf.as_ptr() as usize,
2143        ))
2144    }
2145    #[doc = "conntrack dccp state information"]
2146    pub fn get_protoinfo_dccp(&self) -> Result<IterableProtoinfoDccpAttrs<'a>, ErrorContext> {
2147        let mut iter = self.clone();
2148        iter.pos = 0;
2149        for attr in iter {
2150            if let ProtoinfoAttrs::ProtoinfoDccp(val) = attr? {
2151                return Ok(val);
2152            }
2153        }
2154        Err(ErrorContext::new_missing(
2155            "ProtoinfoAttrs",
2156            "ProtoinfoDccp",
2157            self.orig_loc,
2158            self.buf.as_ptr() as usize,
2159        ))
2160    }
2161    #[doc = "conntrack sctp state information"]
2162    pub fn get_protoinfo_sctp(&self) -> Result<IterableProtoinfoSctpAttrs<'a>, ErrorContext> {
2163        let mut iter = self.clone();
2164        iter.pos = 0;
2165        for attr in iter {
2166            if let ProtoinfoAttrs::ProtoinfoSctp(val) = attr? {
2167                return Ok(val);
2168            }
2169        }
2170        Err(ErrorContext::new_missing(
2171            "ProtoinfoAttrs",
2172            "ProtoinfoSctp",
2173            self.orig_loc,
2174            self.buf.as_ptr() as usize,
2175        ))
2176    }
2177}
2178impl ProtoinfoAttrs<'_> {
2179    pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoAttrs<'a> {
2180        IterableProtoinfoAttrs::with_loc(buf, buf.as_ptr() as usize)
2181    }
2182    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2183        let res = match r#type {
2184            1u16 => "ProtoinfoTcp",
2185            2u16 => "ProtoinfoDccp",
2186            3u16 => "ProtoinfoSctp",
2187            _ => return None,
2188        };
2189        Some(res)
2190    }
2191}
2192#[derive(Clone, Copy, Default)]
2193pub struct IterableProtoinfoAttrs<'a> {
2194    buf: &'a [u8],
2195    pos: usize,
2196    orig_loc: usize,
2197}
2198impl<'a> IterableProtoinfoAttrs<'a> {
2199    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2200        Self {
2201            buf,
2202            pos: 0,
2203            orig_loc,
2204        }
2205    }
2206    pub fn get_buf(&self) -> &'a [u8] {
2207        self.buf
2208    }
2209}
2210impl<'a> Iterator for IterableProtoinfoAttrs<'a> {
2211    type Item = Result<ProtoinfoAttrs<'a>, ErrorContext>;
2212    fn next(&mut self) -> Option<Self::Item> {
2213        let pos = self.pos;
2214        let mut r#type;
2215        loop {
2216            r#type = None;
2217            if self.buf.len() == self.pos {
2218                return None;
2219            }
2220            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2221                break;
2222            };
2223            r#type = Some(header.r#type);
2224            let res = match header.r#type {
2225                1u16 => ProtoinfoAttrs::ProtoinfoTcp({
2226                    let res = Some(IterableProtoinfoTcpAttrs::with_loc(next, self.orig_loc));
2227                    let Some(val) = res else { break };
2228                    val
2229                }),
2230                2u16 => ProtoinfoAttrs::ProtoinfoDccp({
2231                    let res = Some(IterableProtoinfoDccpAttrs::with_loc(next, self.orig_loc));
2232                    let Some(val) = res else { break };
2233                    val
2234                }),
2235                3u16 => ProtoinfoAttrs::ProtoinfoSctp({
2236                    let res = Some(IterableProtoinfoSctpAttrs::with_loc(next, self.orig_loc));
2237                    let Some(val) = res else { break };
2238                    val
2239                }),
2240                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2241                n => continue,
2242            };
2243            return Some(Ok(res));
2244        }
2245        Some(Err(ErrorContext::new(
2246            "ProtoinfoAttrs",
2247            r#type.and_then(|t| ProtoinfoAttrs::attr_from_type(t)),
2248            self.orig_loc,
2249            self.buf.as_ptr().wrapping_add(pos) as usize,
2250        )))
2251    }
2252}
2253impl<'a> std::fmt::Debug for IterableProtoinfoAttrs<'_> {
2254    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2255        let mut fmt = f.debug_struct("ProtoinfoAttrs");
2256        for attr in self.clone() {
2257            let attr = match attr {
2258                Ok(a) => a,
2259                Err(err) => {
2260                    fmt.finish()?;
2261                    f.write_str("Err(")?;
2262                    err.fmt(f)?;
2263                    return f.write_str(")");
2264                }
2265            };
2266            match attr {
2267                ProtoinfoAttrs::ProtoinfoTcp(val) => fmt.field("ProtoinfoTcp", &val),
2268                ProtoinfoAttrs::ProtoinfoDccp(val) => fmt.field("ProtoinfoDccp", &val),
2269                ProtoinfoAttrs::ProtoinfoSctp(val) => fmt.field("ProtoinfoSctp", &val),
2270            };
2271        }
2272        fmt.finish()
2273    }
2274}
2275impl IterableProtoinfoAttrs<'_> {
2276    pub fn lookup_attr(
2277        &self,
2278        offset: usize,
2279        missing_type: Option<u16>,
2280    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2281        let mut stack = Vec::new();
2282        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2283        if missing_type.is_some() && cur == offset {
2284            stack.push(("ProtoinfoAttrs", offset));
2285            return (
2286                stack,
2287                missing_type.and_then(|t| ProtoinfoAttrs::attr_from_type(t)),
2288            );
2289        }
2290        if cur > offset || cur + self.buf.len() < offset {
2291            return (stack, None);
2292        }
2293        let mut attrs = self.clone();
2294        let mut last_off = cur + attrs.pos;
2295        let mut missing = None;
2296        while let Some(attr) = attrs.next() {
2297            let Ok(attr) = attr else { break };
2298            match attr {
2299                ProtoinfoAttrs::ProtoinfoTcp(val) => {
2300                    (stack, missing) = val.lookup_attr(offset, missing_type);
2301                    if !stack.is_empty() {
2302                        break;
2303                    }
2304                }
2305                ProtoinfoAttrs::ProtoinfoDccp(val) => {
2306                    (stack, missing) = val.lookup_attr(offset, missing_type);
2307                    if !stack.is_empty() {
2308                        break;
2309                    }
2310                }
2311                ProtoinfoAttrs::ProtoinfoSctp(val) => {
2312                    (stack, missing) = val.lookup_attr(offset, missing_type);
2313                    if !stack.is_empty() {
2314                        break;
2315                    }
2316                }
2317                _ => {}
2318            };
2319            last_off = cur + attrs.pos;
2320        }
2321        if !stack.is_empty() {
2322            stack.push(("ProtoinfoAttrs", cur));
2323        }
2324        (stack, missing)
2325    }
2326}
2327#[derive(Clone)]
2328pub enum HelpAttrs<'a> {
2329    #[doc = "helper name"]
2330    HelpName(&'a CStr),
2331}
2332impl<'a> IterableHelpAttrs<'a> {
2333    #[doc = "helper name"]
2334    pub fn get_help_name(&self) -> Result<&'a CStr, ErrorContext> {
2335        let mut iter = self.clone();
2336        iter.pos = 0;
2337        for attr in iter {
2338            if let HelpAttrs::HelpName(val) = attr? {
2339                return Ok(val);
2340            }
2341        }
2342        Err(ErrorContext::new_missing(
2343            "HelpAttrs",
2344            "HelpName",
2345            self.orig_loc,
2346            self.buf.as_ptr() as usize,
2347        ))
2348    }
2349}
2350impl HelpAttrs<'_> {
2351    pub fn new<'a>(buf: &'a [u8]) -> IterableHelpAttrs<'a> {
2352        IterableHelpAttrs::with_loc(buf, buf.as_ptr() as usize)
2353    }
2354    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2355        let res = match r#type {
2356            1u16 => "HelpName",
2357            _ => return None,
2358        };
2359        Some(res)
2360    }
2361}
2362#[derive(Clone, Copy, Default)]
2363pub struct IterableHelpAttrs<'a> {
2364    buf: &'a [u8],
2365    pos: usize,
2366    orig_loc: usize,
2367}
2368impl<'a> IterableHelpAttrs<'a> {
2369    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2370        Self {
2371            buf,
2372            pos: 0,
2373            orig_loc,
2374        }
2375    }
2376    pub fn get_buf(&self) -> &'a [u8] {
2377        self.buf
2378    }
2379}
2380impl<'a> Iterator for IterableHelpAttrs<'a> {
2381    type Item = Result<HelpAttrs<'a>, ErrorContext>;
2382    fn next(&mut self) -> Option<Self::Item> {
2383        let pos = self.pos;
2384        let mut r#type;
2385        loop {
2386            r#type = None;
2387            if self.buf.len() == self.pos {
2388                return None;
2389            }
2390            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2391                break;
2392            };
2393            r#type = Some(header.r#type);
2394            let res = match header.r#type {
2395                1u16 => HelpAttrs::HelpName({
2396                    let res = CStr::from_bytes_with_nul(next).ok();
2397                    let Some(val) = res else { break };
2398                    val
2399                }),
2400                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2401                n => continue,
2402            };
2403            return Some(Ok(res));
2404        }
2405        Some(Err(ErrorContext::new(
2406            "HelpAttrs",
2407            r#type.and_then(|t| HelpAttrs::attr_from_type(t)),
2408            self.orig_loc,
2409            self.buf.as_ptr().wrapping_add(pos) as usize,
2410        )))
2411    }
2412}
2413impl<'a> std::fmt::Debug for IterableHelpAttrs<'_> {
2414    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2415        let mut fmt = f.debug_struct("HelpAttrs");
2416        for attr in self.clone() {
2417            let attr = match attr {
2418                Ok(a) => a,
2419                Err(err) => {
2420                    fmt.finish()?;
2421                    f.write_str("Err(")?;
2422                    err.fmt(f)?;
2423                    return f.write_str(")");
2424                }
2425            };
2426            match attr {
2427                HelpAttrs::HelpName(val) => fmt.field("HelpName", &val),
2428            };
2429        }
2430        fmt.finish()
2431    }
2432}
2433impl IterableHelpAttrs<'_> {
2434    pub fn lookup_attr(
2435        &self,
2436        offset: usize,
2437        missing_type: Option<u16>,
2438    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2439        let mut stack = Vec::new();
2440        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2441        if missing_type.is_some() && cur == offset {
2442            stack.push(("HelpAttrs", offset));
2443            return (
2444                stack,
2445                missing_type.and_then(|t| HelpAttrs::attr_from_type(t)),
2446            );
2447        }
2448        if cur > offset || cur + self.buf.len() < offset {
2449            return (stack, None);
2450        }
2451        let mut attrs = self.clone();
2452        let mut last_off = cur + attrs.pos;
2453        while let Some(attr) = attrs.next() {
2454            let Ok(attr) = attr else { break };
2455            match attr {
2456                HelpAttrs::HelpName(val) => {
2457                    if last_off == offset {
2458                        stack.push(("HelpName", last_off));
2459                        break;
2460                    }
2461                }
2462                _ => {}
2463            };
2464            last_off = cur + attrs.pos;
2465        }
2466        if !stack.is_empty() {
2467            stack.push(("HelpAttrs", cur));
2468        }
2469        (stack, None)
2470    }
2471}
2472#[derive(Clone)]
2473pub enum NatProtoAttrs {
2474    NatPortMin(u16),
2475    NatPortMax(u16),
2476}
2477impl<'a> IterableNatProtoAttrs<'a> {
2478    pub fn get_nat_port_min(&self) -> Result<u16, ErrorContext> {
2479        let mut iter = self.clone();
2480        iter.pos = 0;
2481        for attr in iter {
2482            if let NatProtoAttrs::NatPortMin(val) = attr? {
2483                return Ok(val);
2484            }
2485        }
2486        Err(ErrorContext::new_missing(
2487            "NatProtoAttrs",
2488            "NatPortMin",
2489            self.orig_loc,
2490            self.buf.as_ptr() as usize,
2491        ))
2492    }
2493    pub fn get_nat_port_max(&self) -> Result<u16, ErrorContext> {
2494        let mut iter = self.clone();
2495        iter.pos = 0;
2496        for attr in iter {
2497            if let NatProtoAttrs::NatPortMax(val) = attr? {
2498                return Ok(val);
2499            }
2500        }
2501        Err(ErrorContext::new_missing(
2502            "NatProtoAttrs",
2503            "NatPortMax",
2504            self.orig_loc,
2505            self.buf.as_ptr() as usize,
2506        ))
2507    }
2508}
2509impl NatProtoAttrs {
2510    pub fn new<'a>(buf: &'a [u8]) -> IterableNatProtoAttrs<'a> {
2511        IterableNatProtoAttrs::with_loc(buf, buf.as_ptr() as usize)
2512    }
2513    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2514        let res = match r#type {
2515            1u16 => "NatPortMin",
2516            2u16 => "NatPortMax",
2517            _ => return None,
2518        };
2519        Some(res)
2520    }
2521}
2522#[derive(Clone, Copy, Default)]
2523pub struct IterableNatProtoAttrs<'a> {
2524    buf: &'a [u8],
2525    pos: usize,
2526    orig_loc: usize,
2527}
2528impl<'a> IterableNatProtoAttrs<'a> {
2529    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2530        Self {
2531            buf,
2532            pos: 0,
2533            orig_loc,
2534        }
2535    }
2536    pub fn get_buf(&self) -> &'a [u8] {
2537        self.buf
2538    }
2539}
2540impl<'a> Iterator for IterableNatProtoAttrs<'a> {
2541    type Item = Result<NatProtoAttrs, ErrorContext>;
2542    fn next(&mut self) -> Option<Self::Item> {
2543        let pos = self.pos;
2544        let mut r#type;
2545        loop {
2546            r#type = None;
2547            if self.buf.len() == self.pos {
2548                return None;
2549            }
2550            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2551                break;
2552            };
2553            r#type = Some(header.r#type);
2554            let res = match header.r#type {
2555                1u16 => NatProtoAttrs::NatPortMin({
2556                    let res = parse_be_u16(next);
2557                    let Some(val) = res else { break };
2558                    val
2559                }),
2560                2u16 => NatProtoAttrs::NatPortMax({
2561                    let res = parse_be_u16(next);
2562                    let Some(val) = res else { break };
2563                    val
2564                }),
2565                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2566                n => continue,
2567            };
2568            return Some(Ok(res));
2569        }
2570        Some(Err(ErrorContext::new(
2571            "NatProtoAttrs",
2572            r#type.and_then(|t| NatProtoAttrs::attr_from_type(t)),
2573            self.orig_loc,
2574            self.buf.as_ptr().wrapping_add(pos) as usize,
2575        )))
2576    }
2577}
2578impl std::fmt::Debug for IterableNatProtoAttrs<'_> {
2579    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2580        let mut fmt = f.debug_struct("NatProtoAttrs");
2581        for attr in self.clone() {
2582            let attr = match attr {
2583                Ok(a) => a,
2584                Err(err) => {
2585                    fmt.finish()?;
2586                    f.write_str("Err(")?;
2587                    err.fmt(f)?;
2588                    return f.write_str(")");
2589                }
2590            };
2591            match attr {
2592                NatProtoAttrs::NatPortMin(val) => fmt.field("NatPortMin", &val),
2593                NatProtoAttrs::NatPortMax(val) => fmt.field("NatPortMax", &val),
2594            };
2595        }
2596        fmt.finish()
2597    }
2598}
2599impl IterableNatProtoAttrs<'_> {
2600    pub fn lookup_attr(
2601        &self,
2602        offset: usize,
2603        missing_type: Option<u16>,
2604    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2605        let mut stack = Vec::new();
2606        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2607        if missing_type.is_some() && cur == offset {
2608            stack.push(("NatProtoAttrs", offset));
2609            return (
2610                stack,
2611                missing_type.and_then(|t| NatProtoAttrs::attr_from_type(t)),
2612            );
2613        }
2614        if cur > offset || cur + self.buf.len() < offset {
2615            return (stack, None);
2616        }
2617        let mut attrs = self.clone();
2618        let mut last_off = cur + attrs.pos;
2619        while let Some(attr) = attrs.next() {
2620            let Ok(attr) = attr else { break };
2621            match attr {
2622                NatProtoAttrs::NatPortMin(val) => {
2623                    if last_off == offset {
2624                        stack.push(("NatPortMin", last_off));
2625                        break;
2626                    }
2627                }
2628                NatProtoAttrs::NatPortMax(val) => {
2629                    if last_off == offset {
2630                        stack.push(("NatPortMax", last_off));
2631                        break;
2632                    }
2633                }
2634                _ => {}
2635            };
2636            last_off = cur + attrs.pos;
2637        }
2638        if !stack.is_empty() {
2639            stack.push(("NatProtoAttrs", cur));
2640        }
2641        (stack, None)
2642    }
2643}
2644#[derive(Clone)]
2645pub enum NatAttrs<'a> {
2646    NatV4Minip(u32),
2647    NatV4Maxip(u32),
2648    NatV6Minip(&'a [u8]),
2649    NatV6Maxip(&'a [u8]),
2650    NatProto(IterableNatProtoAttrs<'a>),
2651}
2652impl<'a> IterableNatAttrs<'a> {
2653    pub fn get_nat_v4_minip(&self) -> Result<u32, ErrorContext> {
2654        let mut iter = self.clone();
2655        iter.pos = 0;
2656        for attr in iter {
2657            if let NatAttrs::NatV4Minip(val) = attr? {
2658                return Ok(val);
2659            }
2660        }
2661        Err(ErrorContext::new_missing(
2662            "NatAttrs",
2663            "NatV4Minip",
2664            self.orig_loc,
2665            self.buf.as_ptr() as usize,
2666        ))
2667    }
2668    pub fn get_nat_v4_maxip(&self) -> Result<u32, ErrorContext> {
2669        let mut iter = self.clone();
2670        iter.pos = 0;
2671        for attr in iter {
2672            if let NatAttrs::NatV4Maxip(val) = attr? {
2673                return Ok(val);
2674            }
2675        }
2676        Err(ErrorContext::new_missing(
2677            "NatAttrs",
2678            "NatV4Maxip",
2679            self.orig_loc,
2680            self.buf.as_ptr() as usize,
2681        ))
2682    }
2683    pub fn get_nat_v6_minip(&self) -> Result<&'a [u8], ErrorContext> {
2684        let mut iter = self.clone();
2685        iter.pos = 0;
2686        for attr in iter {
2687            if let NatAttrs::NatV6Minip(val) = attr? {
2688                return Ok(val);
2689            }
2690        }
2691        Err(ErrorContext::new_missing(
2692            "NatAttrs",
2693            "NatV6Minip",
2694            self.orig_loc,
2695            self.buf.as_ptr() as usize,
2696        ))
2697    }
2698    pub fn get_nat_v6_maxip(&self) -> Result<&'a [u8], ErrorContext> {
2699        let mut iter = self.clone();
2700        iter.pos = 0;
2701        for attr in iter {
2702            if let NatAttrs::NatV6Maxip(val) = attr? {
2703                return Ok(val);
2704            }
2705        }
2706        Err(ErrorContext::new_missing(
2707            "NatAttrs",
2708            "NatV6Maxip",
2709            self.orig_loc,
2710            self.buf.as_ptr() as usize,
2711        ))
2712    }
2713    pub fn get_nat_proto(&self) -> Result<IterableNatProtoAttrs<'a>, ErrorContext> {
2714        let mut iter = self.clone();
2715        iter.pos = 0;
2716        for attr in iter {
2717            if let NatAttrs::NatProto(val) = attr? {
2718                return Ok(val);
2719            }
2720        }
2721        Err(ErrorContext::new_missing(
2722            "NatAttrs",
2723            "NatProto",
2724            self.orig_loc,
2725            self.buf.as_ptr() as usize,
2726        ))
2727    }
2728}
2729impl NatAttrs<'_> {
2730    pub fn new<'a>(buf: &'a [u8]) -> IterableNatAttrs<'a> {
2731        IterableNatAttrs::with_loc(buf, buf.as_ptr() as usize)
2732    }
2733    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2734        let res = match r#type {
2735            1u16 => "NatV4Minip",
2736            2u16 => "NatV4Maxip",
2737            3u16 => "NatV6Minip",
2738            4u16 => "NatV6Maxip",
2739            5u16 => "NatProto",
2740            _ => return None,
2741        };
2742        Some(res)
2743    }
2744}
2745#[derive(Clone, Copy, Default)]
2746pub struct IterableNatAttrs<'a> {
2747    buf: &'a [u8],
2748    pos: usize,
2749    orig_loc: usize,
2750}
2751impl<'a> IterableNatAttrs<'a> {
2752    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2753        Self {
2754            buf,
2755            pos: 0,
2756            orig_loc,
2757        }
2758    }
2759    pub fn get_buf(&self) -> &'a [u8] {
2760        self.buf
2761    }
2762}
2763impl<'a> Iterator for IterableNatAttrs<'a> {
2764    type Item = Result<NatAttrs<'a>, ErrorContext>;
2765    fn next(&mut self) -> Option<Self::Item> {
2766        let pos = self.pos;
2767        let mut r#type;
2768        loop {
2769            r#type = None;
2770            if self.buf.len() == self.pos {
2771                return None;
2772            }
2773            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2774                break;
2775            };
2776            r#type = Some(header.r#type);
2777            let res = match header.r#type {
2778                1u16 => NatAttrs::NatV4Minip({
2779                    let res = parse_be_u32(next);
2780                    let Some(val) = res else { break };
2781                    val
2782                }),
2783                2u16 => NatAttrs::NatV4Maxip({
2784                    let res = parse_be_u32(next);
2785                    let Some(val) = res else { break };
2786                    val
2787                }),
2788                3u16 => NatAttrs::NatV6Minip({
2789                    let res = Some(next);
2790                    let Some(val) = res else { break };
2791                    val
2792                }),
2793                4u16 => NatAttrs::NatV6Maxip({
2794                    let res = Some(next);
2795                    let Some(val) = res else { break };
2796                    val
2797                }),
2798                5u16 => NatAttrs::NatProto({
2799                    let res = Some(IterableNatProtoAttrs::with_loc(next, self.orig_loc));
2800                    let Some(val) = res else { break };
2801                    val
2802                }),
2803                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2804                n => continue,
2805            };
2806            return Some(Ok(res));
2807        }
2808        Some(Err(ErrorContext::new(
2809            "NatAttrs",
2810            r#type.and_then(|t| NatAttrs::attr_from_type(t)),
2811            self.orig_loc,
2812            self.buf.as_ptr().wrapping_add(pos) as usize,
2813        )))
2814    }
2815}
2816impl<'a> std::fmt::Debug for IterableNatAttrs<'_> {
2817    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2818        let mut fmt = f.debug_struct("NatAttrs");
2819        for attr in self.clone() {
2820            let attr = match attr {
2821                Ok(a) => a,
2822                Err(err) => {
2823                    fmt.finish()?;
2824                    f.write_str("Err(")?;
2825                    err.fmt(f)?;
2826                    return f.write_str(")");
2827                }
2828            };
2829            match attr {
2830                NatAttrs::NatV4Minip(val) => fmt.field("NatV4Minip", &val),
2831                NatAttrs::NatV4Maxip(val) => fmt.field("NatV4Maxip", &val),
2832                NatAttrs::NatV6Minip(val) => fmt.field("NatV6Minip", &val),
2833                NatAttrs::NatV6Maxip(val) => fmt.field("NatV6Maxip", &val),
2834                NatAttrs::NatProto(val) => fmt.field("NatProto", &val),
2835            };
2836        }
2837        fmt.finish()
2838    }
2839}
2840impl IterableNatAttrs<'_> {
2841    pub fn lookup_attr(
2842        &self,
2843        offset: usize,
2844        missing_type: Option<u16>,
2845    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2846        let mut stack = Vec::new();
2847        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2848        if missing_type.is_some() && cur == offset {
2849            stack.push(("NatAttrs", offset));
2850            return (
2851                stack,
2852                missing_type.and_then(|t| NatAttrs::attr_from_type(t)),
2853            );
2854        }
2855        if cur > offset || cur + self.buf.len() < offset {
2856            return (stack, None);
2857        }
2858        let mut attrs = self.clone();
2859        let mut last_off = cur + attrs.pos;
2860        let mut missing = None;
2861        while let Some(attr) = attrs.next() {
2862            let Ok(attr) = attr else { break };
2863            match attr {
2864                NatAttrs::NatV4Minip(val) => {
2865                    if last_off == offset {
2866                        stack.push(("NatV4Minip", last_off));
2867                        break;
2868                    }
2869                }
2870                NatAttrs::NatV4Maxip(val) => {
2871                    if last_off == offset {
2872                        stack.push(("NatV4Maxip", last_off));
2873                        break;
2874                    }
2875                }
2876                NatAttrs::NatV6Minip(val) => {
2877                    if last_off == offset {
2878                        stack.push(("NatV6Minip", last_off));
2879                        break;
2880                    }
2881                }
2882                NatAttrs::NatV6Maxip(val) => {
2883                    if last_off == offset {
2884                        stack.push(("NatV6Maxip", last_off));
2885                        break;
2886                    }
2887                }
2888                NatAttrs::NatProto(val) => {
2889                    (stack, missing) = val.lookup_attr(offset, missing_type);
2890                    if !stack.is_empty() {
2891                        break;
2892                    }
2893                }
2894                _ => {}
2895            };
2896            last_off = cur + attrs.pos;
2897        }
2898        if !stack.is_empty() {
2899            stack.push(("NatAttrs", cur));
2900        }
2901        (stack, missing)
2902    }
2903}
2904#[derive(Clone)]
2905pub enum SeqadjAttrs {
2906    CorrectionPos(u32),
2907    OffsetBefore(u32),
2908    OffsetAfter(u32),
2909}
2910impl<'a> IterableSeqadjAttrs<'a> {
2911    pub fn get_correction_pos(&self) -> Result<u32, ErrorContext> {
2912        let mut iter = self.clone();
2913        iter.pos = 0;
2914        for attr in iter {
2915            if let SeqadjAttrs::CorrectionPos(val) = attr? {
2916                return Ok(val);
2917            }
2918        }
2919        Err(ErrorContext::new_missing(
2920            "SeqadjAttrs",
2921            "CorrectionPos",
2922            self.orig_loc,
2923            self.buf.as_ptr() as usize,
2924        ))
2925    }
2926    pub fn get_offset_before(&self) -> Result<u32, ErrorContext> {
2927        let mut iter = self.clone();
2928        iter.pos = 0;
2929        for attr in iter {
2930            if let SeqadjAttrs::OffsetBefore(val) = attr? {
2931                return Ok(val);
2932            }
2933        }
2934        Err(ErrorContext::new_missing(
2935            "SeqadjAttrs",
2936            "OffsetBefore",
2937            self.orig_loc,
2938            self.buf.as_ptr() as usize,
2939        ))
2940    }
2941    pub fn get_offset_after(&self) -> Result<u32, ErrorContext> {
2942        let mut iter = self.clone();
2943        iter.pos = 0;
2944        for attr in iter {
2945            if let SeqadjAttrs::OffsetAfter(val) = attr? {
2946                return Ok(val);
2947            }
2948        }
2949        Err(ErrorContext::new_missing(
2950            "SeqadjAttrs",
2951            "OffsetAfter",
2952            self.orig_loc,
2953            self.buf.as_ptr() as usize,
2954        ))
2955    }
2956}
2957impl SeqadjAttrs {
2958    pub fn new<'a>(buf: &'a [u8]) -> IterableSeqadjAttrs<'a> {
2959        IterableSeqadjAttrs::with_loc(buf, buf.as_ptr() as usize)
2960    }
2961    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2962        let res = match r#type {
2963            1u16 => "CorrectionPos",
2964            2u16 => "OffsetBefore",
2965            3u16 => "OffsetAfter",
2966            _ => return None,
2967        };
2968        Some(res)
2969    }
2970}
2971#[derive(Clone, Copy, Default)]
2972pub struct IterableSeqadjAttrs<'a> {
2973    buf: &'a [u8],
2974    pos: usize,
2975    orig_loc: usize,
2976}
2977impl<'a> IterableSeqadjAttrs<'a> {
2978    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2979        Self {
2980            buf,
2981            pos: 0,
2982            orig_loc,
2983        }
2984    }
2985    pub fn get_buf(&self) -> &'a [u8] {
2986        self.buf
2987    }
2988}
2989impl<'a> Iterator for IterableSeqadjAttrs<'a> {
2990    type Item = Result<SeqadjAttrs, ErrorContext>;
2991    fn next(&mut self) -> Option<Self::Item> {
2992        let pos = self.pos;
2993        let mut r#type;
2994        loop {
2995            r#type = None;
2996            if self.buf.len() == self.pos {
2997                return None;
2998            }
2999            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3000                break;
3001            };
3002            r#type = Some(header.r#type);
3003            let res = match header.r#type {
3004                1u16 => SeqadjAttrs::CorrectionPos({
3005                    let res = parse_be_u32(next);
3006                    let Some(val) = res else { break };
3007                    val
3008                }),
3009                2u16 => SeqadjAttrs::OffsetBefore({
3010                    let res = parse_be_u32(next);
3011                    let Some(val) = res else { break };
3012                    val
3013                }),
3014                3u16 => SeqadjAttrs::OffsetAfter({
3015                    let res = parse_be_u32(next);
3016                    let Some(val) = res else { break };
3017                    val
3018                }),
3019                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3020                n => continue,
3021            };
3022            return Some(Ok(res));
3023        }
3024        Some(Err(ErrorContext::new(
3025            "SeqadjAttrs",
3026            r#type.and_then(|t| SeqadjAttrs::attr_from_type(t)),
3027            self.orig_loc,
3028            self.buf.as_ptr().wrapping_add(pos) as usize,
3029        )))
3030    }
3031}
3032impl std::fmt::Debug for IterableSeqadjAttrs<'_> {
3033    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3034        let mut fmt = f.debug_struct("SeqadjAttrs");
3035        for attr in self.clone() {
3036            let attr = match attr {
3037                Ok(a) => a,
3038                Err(err) => {
3039                    fmt.finish()?;
3040                    f.write_str("Err(")?;
3041                    err.fmt(f)?;
3042                    return f.write_str(")");
3043                }
3044            };
3045            match attr {
3046                SeqadjAttrs::CorrectionPos(val) => fmt.field("CorrectionPos", &val),
3047                SeqadjAttrs::OffsetBefore(val) => fmt.field("OffsetBefore", &val),
3048                SeqadjAttrs::OffsetAfter(val) => fmt.field("OffsetAfter", &val),
3049            };
3050        }
3051        fmt.finish()
3052    }
3053}
3054impl IterableSeqadjAttrs<'_> {
3055    pub fn lookup_attr(
3056        &self,
3057        offset: usize,
3058        missing_type: Option<u16>,
3059    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3060        let mut stack = Vec::new();
3061        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3062        if missing_type.is_some() && cur == offset {
3063            stack.push(("SeqadjAttrs", offset));
3064            return (
3065                stack,
3066                missing_type.and_then(|t| SeqadjAttrs::attr_from_type(t)),
3067            );
3068        }
3069        if cur > offset || cur + self.buf.len() < offset {
3070            return (stack, None);
3071        }
3072        let mut attrs = self.clone();
3073        let mut last_off = cur + attrs.pos;
3074        while let Some(attr) = attrs.next() {
3075            let Ok(attr) = attr else { break };
3076            match attr {
3077                SeqadjAttrs::CorrectionPos(val) => {
3078                    if last_off == offset {
3079                        stack.push(("CorrectionPos", last_off));
3080                        break;
3081                    }
3082                }
3083                SeqadjAttrs::OffsetBefore(val) => {
3084                    if last_off == offset {
3085                        stack.push(("OffsetBefore", last_off));
3086                        break;
3087                    }
3088                }
3089                SeqadjAttrs::OffsetAfter(val) => {
3090                    if last_off == offset {
3091                        stack.push(("OffsetAfter", last_off));
3092                        break;
3093                    }
3094                }
3095                _ => {}
3096            };
3097            last_off = cur + attrs.pos;
3098        }
3099        if !stack.is_empty() {
3100            stack.push(("SeqadjAttrs", cur));
3101        }
3102        (stack, None)
3103    }
3104}
3105#[derive(Clone)]
3106pub enum SecctxAttrs<'a> {
3107    SecctxName(&'a CStr),
3108}
3109impl<'a> IterableSecctxAttrs<'a> {
3110    pub fn get_secctx_name(&self) -> Result<&'a CStr, ErrorContext> {
3111        let mut iter = self.clone();
3112        iter.pos = 0;
3113        for attr in iter {
3114            if let SecctxAttrs::SecctxName(val) = attr? {
3115                return Ok(val);
3116            }
3117        }
3118        Err(ErrorContext::new_missing(
3119            "SecctxAttrs",
3120            "SecctxName",
3121            self.orig_loc,
3122            self.buf.as_ptr() as usize,
3123        ))
3124    }
3125}
3126impl SecctxAttrs<'_> {
3127    pub fn new<'a>(buf: &'a [u8]) -> IterableSecctxAttrs<'a> {
3128        IterableSecctxAttrs::with_loc(buf, buf.as_ptr() as usize)
3129    }
3130    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3131        let res = match r#type {
3132            1u16 => "SecctxName",
3133            _ => return None,
3134        };
3135        Some(res)
3136    }
3137}
3138#[derive(Clone, Copy, Default)]
3139pub struct IterableSecctxAttrs<'a> {
3140    buf: &'a [u8],
3141    pos: usize,
3142    orig_loc: usize,
3143}
3144impl<'a> IterableSecctxAttrs<'a> {
3145    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3146        Self {
3147            buf,
3148            pos: 0,
3149            orig_loc,
3150        }
3151    }
3152    pub fn get_buf(&self) -> &'a [u8] {
3153        self.buf
3154    }
3155}
3156impl<'a> Iterator for IterableSecctxAttrs<'a> {
3157    type Item = Result<SecctxAttrs<'a>, ErrorContext>;
3158    fn next(&mut self) -> Option<Self::Item> {
3159        let pos = self.pos;
3160        let mut r#type;
3161        loop {
3162            r#type = None;
3163            if self.buf.len() == self.pos {
3164                return None;
3165            }
3166            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3167                break;
3168            };
3169            r#type = Some(header.r#type);
3170            let res = match header.r#type {
3171                1u16 => SecctxAttrs::SecctxName({
3172                    let res = CStr::from_bytes_with_nul(next).ok();
3173                    let Some(val) = res else { break };
3174                    val
3175                }),
3176                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3177                n => continue,
3178            };
3179            return Some(Ok(res));
3180        }
3181        Some(Err(ErrorContext::new(
3182            "SecctxAttrs",
3183            r#type.and_then(|t| SecctxAttrs::attr_from_type(t)),
3184            self.orig_loc,
3185            self.buf.as_ptr().wrapping_add(pos) as usize,
3186        )))
3187    }
3188}
3189impl<'a> std::fmt::Debug for IterableSecctxAttrs<'_> {
3190    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3191        let mut fmt = f.debug_struct("SecctxAttrs");
3192        for attr in self.clone() {
3193            let attr = match attr {
3194                Ok(a) => a,
3195                Err(err) => {
3196                    fmt.finish()?;
3197                    f.write_str("Err(")?;
3198                    err.fmt(f)?;
3199                    return f.write_str(")");
3200                }
3201            };
3202            match attr {
3203                SecctxAttrs::SecctxName(val) => fmt.field("SecctxName", &val),
3204            };
3205        }
3206        fmt.finish()
3207    }
3208}
3209impl IterableSecctxAttrs<'_> {
3210    pub fn lookup_attr(
3211        &self,
3212        offset: usize,
3213        missing_type: Option<u16>,
3214    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3215        let mut stack = Vec::new();
3216        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3217        if missing_type.is_some() && cur == offset {
3218            stack.push(("SecctxAttrs", offset));
3219            return (
3220                stack,
3221                missing_type.and_then(|t| SecctxAttrs::attr_from_type(t)),
3222            );
3223        }
3224        if cur > offset || cur + self.buf.len() < offset {
3225            return (stack, None);
3226        }
3227        let mut attrs = self.clone();
3228        let mut last_off = cur + attrs.pos;
3229        while let Some(attr) = attrs.next() {
3230            let Ok(attr) = attr else { break };
3231            match attr {
3232                SecctxAttrs::SecctxName(val) => {
3233                    if last_off == offset {
3234                        stack.push(("SecctxName", last_off));
3235                        break;
3236                    }
3237                }
3238                _ => {}
3239            };
3240            last_off = cur + attrs.pos;
3241        }
3242        if !stack.is_empty() {
3243            stack.push(("SecctxAttrs", cur));
3244        }
3245        (stack, None)
3246    }
3247}
3248#[derive(Clone)]
3249pub enum SynproxyAttrs {
3250    Isn(u32),
3251    Its(u32),
3252    Tsoff(u32),
3253}
3254impl<'a> IterableSynproxyAttrs<'a> {
3255    pub fn get_isn(&self) -> Result<u32, ErrorContext> {
3256        let mut iter = self.clone();
3257        iter.pos = 0;
3258        for attr in iter {
3259            if let SynproxyAttrs::Isn(val) = attr? {
3260                return Ok(val);
3261            }
3262        }
3263        Err(ErrorContext::new_missing(
3264            "SynproxyAttrs",
3265            "Isn",
3266            self.orig_loc,
3267            self.buf.as_ptr() as usize,
3268        ))
3269    }
3270    pub fn get_its(&self) -> Result<u32, ErrorContext> {
3271        let mut iter = self.clone();
3272        iter.pos = 0;
3273        for attr in iter {
3274            if let SynproxyAttrs::Its(val) = attr? {
3275                return Ok(val);
3276            }
3277        }
3278        Err(ErrorContext::new_missing(
3279            "SynproxyAttrs",
3280            "Its",
3281            self.orig_loc,
3282            self.buf.as_ptr() as usize,
3283        ))
3284    }
3285    pub fn get_tsoff(&self) -> Result<u32, ErrorContext> {
3286        let mut iter = self.clone();
3287        iter.pos = 0;
3288        for attr in iter {
3289            if let SynproxyAttrs::Tsoff(val) = attr? {
3290                return Ok(val);
3291            }
3292        }
3293        Err(ErrorContext::new_missing(
3294            "SynproxyAttrs",
3295            "Tsoff",
3296            self.orig_loc,
3297            self.buf.as_ptr() as usize,
3298        ))
3299    }
3300}
3301impl SynproxyAttrs {
3302    pub fn new<'a>(buf: &'a [u8]) -> IterableSynproxyAttrs<'a> {
3303        IterableSynproxyAttrs::with_loc(buf, buf.as_ptr() as usize)
3304    }
3305    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3306        let res = match r#type {
3307            1u16 => "Isn",
3308            2u16 => "Its",
3309            3u16 => "Tsoff",
3310            _ => return None,
3311        };
3312        Some(res)
3313    }
3314}
3315#[derive(Clone, Copy, Default)]
3316pub struct IterableSynproxyAttrs<'a> {
3317    buf: &'a [u8],
3318    pos: usize,
3319    orig_loc: usize,
3320}
3321impl<'a> IterableSynproxyAttrs<'a> {
3322    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3323        Self {
3324            buf,
3325            pos: 0,
3326            orig_loc,
3327        }
3328    }
3329    pub fn get_buf(&self) -> &'a [u8] {
3330        self.buf
3331    }
3332}
3333impl<'a> Iterator for IterableSynproxyAttrs<'a> {
3334    type Item = Result<SynproxyAttrs, ErrorContext>;
3335    fn next(&mut self) -> Option<Self::Item> {
3336        let pos = self.pos;
3337        let mut r#type;
3338        loop {
3339            r#type = None;
3340            if self.buf.len() == self.pos {
3341                return None;
3342            }
3343            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3344                break;
3345            };
3346            r#type = Some(header.r#type);
3347            let res = match header.r#type {
3348                1u16 => SynproxyAttrs::Isn({
3349                    let res = parse_be_u32(next);
3350                    let Some(val) = res else { break };
3351                    val
3352                }),
3353                2u16 => SynproxyAttrs::Its({
3354                    let res = parse_be_u32(next);
3355                    let Some(val) = res else { break };
3356                    val
3357                }),
3358                3u16 => SynproxyAttrs::Tsoff({
3359                    let res = parse_be_u32(next);
3360                    let Some(val) = res else { break };
3361                    val
3362                }),
3363                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3364                n => continue,
3365            };
3366            return Some(Ok(res));
3367        }
3368        Some(Err(ErrorContext::new(
3369            "SynproxyAttrs",
3370            r#type.and_then(|t| SynproxyAttrs::attr_from_type(t)),
3371            self.orig_loc,
3372            self.buf.as_ptr().wrapping_add(pos) as usize,
3373        )))
3374    }
3375}
3376impl std::fmt::Debug for IterableSynproxyAttrs<'_> {
3377    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3378        let mut fmt = f.debug_struct("SynproxyAttrs");
3379        for attr in self.clone() {
3380            let attr = match attr {
3381                Ok(a) => a,
3382                Err(err) => {
3383                    fmt.finish()?;
3384                    f.write_str("Err(")?;
3385                    err.fmt(f)?;
3386                    return f.write_str(")");
3387                }
3388            };
3389            match attr {
3390                SynproxyAttrs::Isn(val) => fmt.field("Isn", &val),
3391                SynproxyAttrs::Its(val) => fmt.field("Its", &val),
3392                SynproxyAttrs::Tsoff(val) => fmt.field("Tsoff", &val),
3393            };
3394        }
3395        fmt.finish()
3396    }
3397}
3398impl IterableSynproxyAttrs<'_> {
3399    pub fn lookup_attr(
3400        &self,
3401        offset: usize,
3402        missing_type: Option<u16>,
3403    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3404        let mut stack = Vec::new();
3405        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3406        if missing_type.is_some() && cur == offset {
3407            stack.push(("SynproxyAttrs", offset));
3408            return (
3409                stack,
3410                missing_type.and_then(|t| SynproxyAttrs::attr_from_type(t)),
3411            );
3412        }
3413        if cur > offset || cur + self.buf.len() < offset {
3414            return (stack, None);
3415        }
3416        let mut attrs = self.clone();
3417        let mut last_off = cur + attrs.pos;
3418        while let Some(attr) = attrs.next() {
3419            let Ok(attr) = attr else { break };
3420            match attr {
3421                SynproxyAttrs::Isn(val) => {
3422                    if last_off == offset {
3423                        stack.push(("Isn", last_off));
3424                        break;
3425                    }
3426                }
3427                SynproxyAttrs::Its(val) => {
3428                    if last_off == offset {
3429                        stack.push(("Its", last_off));
3430                        break;
3431                    }
3432                }
3433                SynproxyAttrs::Tsoff(val) => {
3434                    if last_off == offset {
3435                        stack.push(("Tsoff", last_off));
3436                        break;
3437                    }
3438                }
3439                _ => {}
3440            };
3441            last_off = cur + attrs.pos;
3442        }
3443        if !stack.is_empty() {
3444            stack.push(("SynproxyAttrs", cur));
3445        }
3446        (stack, None)
3447    }
3448}
3449#[derive(Clone)]
3450pub enum ConntrackAttrs<'a> {
3451    #[doc = "conntrack l3\\+l4 protocol information, original direction"]
3452    TupleOrig(IterableTupleAttrs<'a>),
3453    #[doc = "conntrack l3\\+l4 protocol information, reply direction"]
3454    TupleReply(IterableTupleAttrs<'a>),
3455    #[doc = "conntrack flag bits\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
3456    Status(u32),
3457    Protoinfo(IterableProtoinfoAttrs<'a>),
3458    Help(IterableHelpAttrs<'a>),
3459    NatSrc(IterableNatAttrs<'a>),
3460    Timeout(u32),
3461    Mark(u32),
3462    CountersOrig(IterableCounterAttrs<'a>),
3463    CountersReply(IterableCounterAttrs<'a>),
3464    Use(u32),
3465    Id(u32),
3466    NatDst(IterableNatAttrs<'a>),
3467    TupleMaster(IterableTupleAttrs<'a>),
3468    SeqAdjOrig(IterableSeqadjAttrs<'a>),
3469    SeqAdjReply(IterableSeqadjAttrs<'a>),
3470    #[doc = "obsolete"]
3471    Secmark(&'a [u8]),
3472    #[doc = "conntrack zone id"]
3473    Zone(u16),
3474    Secctx(IterableSecctxAttrs<'a>),
3475    Timestamp(u64),
3476    MarkMask(u32),
3477    Labels(&'a [u8]),
3478    LabelsMask(&'a [u8]),
3479    Synproxy(IterableSynproxyAttrs<'a>),
3480    Filter(IterableTupleAttrs<'a>),
3481    #[doc = "conntrack flag bits to change\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
3482    StatusMask(u32),
3483    TimestampEvent(u64),
3484}
3485impl<'a> IterableConntrackAttrs<'a> {
3486    #[doc = "conntrack l3\\+l4 protocol information, original direction"]
3487    pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3488        let mut iter = self.clone();
3489        iter.pos = 0;
3490        for attr in iter {
3491            if let ConntrackAttrs::TupleOrig(val) = attr? {
3492                return Ok(val);
3493            }
3494        }
3495        Err(ErrorContext::new_missing(
3496            "ConntrackAttrs",
3497            "TupleOrig",
3498            self.orig_loc,
3499            self.buf.as_ptr() as usize,
3500        ))
3501    }
3502    #[doc = "conntrack l3\\+l4 protocol information, reply direction"]
3503    pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3504        let mut iter = self.clone();
3505        iter.pos = 0;
3506        for attr in iter {
3507            if let ConntrackAttrs::TupleReply(val) = attr? {
3508                return Ok(val);
3509            }
3510        }
3511        Err(ErrorContext::new_missing(
3512            "ConntrackAttrs",
3513            "TupleReply",
3514            self.orig_loc,
3515            self.buf.as_ptr() as usize,
3516        ))
3517    }
3518    #[doc = "conntrack flag bits\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
3519    pub fn get_status(&self) -> Result<u32, ErrorContext> {
3520        let mut iter = self.clone();
3521        iter.pos = 0;
3522        for attr in iter {
3523            if let ConntrackAttrs::Status(val) = attr? {
3524                return Ok(val);
3525            }
3526        }
3527        Err(ErrorContext::new_missing(
3528            "ConntrackAttrs",
3529            "Status",
3530            self.orig_loc,
3531            self.buf.as_ptr() as usize,
3532        ))
3533    }
3534    pub fn get_protoinfo(&self) -> Result<IterableProtoinfoAttrs<'a>, ErrorContext> {
3535        let mut iter = self.clone();
3536        iter.pos = 0;
3537        for attr in iter {
3538            if let ConntrackAttrs::Protoinfo(val) = attr? {
3539                return Ok(val);
3540            }
3541        }
3542        Err(ErrorContext::new_missing(
3543            "ConntrackAttrs",
3544            "Protoinfo",
3545            self.orig_loc,
3546            self.buf.as_ptr() as usize,
3547        ))
3548    }
3549    pub fn get_help(&self) -> Result<IterableHelpAttrs<'a>, ErrorContext> {
3550        let mut iter = self.clone();
3551        iter.pos = 0;
3552        for attr in iter {
3553            if let ConntrackAttrs::Help(val) = attr? {
3554                return Ok(val);
3555            }
3556        }
3557        Err(ErrorContext::new_missing(
3558            "ConntrackAttrs",
3559            "Help",
3560            self.orig_loc,
3561            self.buf.as_ptr() as usize,
3562        ))
3563    }
3564    pub fn get_nat_src(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
3565        let mut iter = self.clone();
3566        iter.pos = 0;
3567        for attr in iter {
3568            if let ConntrackAttrs::NatSrc(val) = attr? {
3569                return Ok(val);
3570            }
3571        }
3572        Err(ErrorContext::new_missing(
3573            "ConntrackAttrs",
3574            "NatSrc",
3575            self.orig_loc,
3576            self.buf.as_ptr() as usize,
3577        ))
3578    }
3579    pub fn get_timeout(&self) -> Result<u32, ErrorContext> {
3580        let mut iter = self.clone();
3581        iter.pos = 0;
3582        for attr in iter {
3583            if let ConntrackAttrs::Timeout(val) = attr? {
3584                return Ok(val);
3585            }
3586        }
3587        Err(ErrorContext::new_missing(
3588            "ConntrackAttrs",
3589            "Timeout",
3590            self.orig_loc,
3591            self.buf.as_ptr() as usize,
3592        ))
3593    }
3594    pub fn get_mark(&self) -> Result<u32, ErrorContext> {
3595        let mut iter = self.clone();
3596        iter.pos = 0;
3597        for attr in iter {
3598            if let ConntrackAttrs::Mark(val) = attr? {
3599                return Ok(val);
3600            }
3601        }
3602        Err(ErrorContext::new_missing(
3603            "ConntrackAttrs",
3604            "Mark",
3605            self.orig_loc,
3606            self.buf.as_ptr() as usize,
3607        ))
3608    }
3609    pub fn get_counters_orig(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
3610        let mut iter = self.clone();
3611        iter.pos = 0;
3612        for attr in iter {
3613            if let ConntrackAttrs::CountersOrig(val) = attr? {
3614                return Ok(val);
3615            }
3616        }
3617        Err(ErrorContext::new_missing(
3618            "ConntrackAttrs",
3619            "CountersOrig",
3620            self.orig_loc,
3621            self.buf.as_ptr() as usize,
3622        ))
3623    }
3624    pub fn get_counters_reply(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
3625        let mut iter = self.clone();
3626        iter.pos = 0;
3627        for attr in iter {
3628            if let ConntrackAttrs::CountersReply(val) = attr? {
3629                return Ok(val);
3630            }
3631        }
3632        Err(ErrorContext::new_missing(
3633            "ConntrackAttrs",
3634            "CountersReply",
3635            self.orig_loc,
3636            self.buf.as_ptr() as usize,
3637        ))
3638    }
3639    pub fn get_use(&self) -> Result<u32, ErrorContext> {
3640        let mut iter = self.clone();
3641        iter.pos = 0;
3642        for attr in iter {
3643            if let ConntrackAttrs::Use(val) = attr? {
3644                return Ok(val);
3645            }
3646        }
3647        Err(ErrorContext::new_missing(
3648            "ConntrackAttrs",
3649            "Use",
3650            self.orig_loc,
3651            self.buf.as_ptr() as usize,
3652        ))
3653    }
3654    pub fn get_id(&self) -> Result<u32, ErrorContext> {
3655        let mut iter = self.clone();
3656        iter.pos = 0;
3657        for attr in iter {
3658            if let ConntrackAttrs::Id(val) = attr? {
3659                return Ok(val);
3660            }
3661        }
3662        Err(ErrorContext::new_missing(
3663            "ConntrackAttrs",
3664            "Id",
3665            self.orig_loc,
3666            self.buf.as_ptr() as usize,
3667        ))
3668    }
3669    pub fn get_nat_dst(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
3670        let mut iter = self.clone();
3671        iter.pos = 0;
3672        for attr in iter {
3673            if let ConntrackAttrs::NatDst(val) = attr? {
3674                return Ok(val);
3675            }
3676        }
3677        Err(ErrorContext::new_missing(
3678            "ConntrackAttrs",
3679            "NatDst",
3680            self.orig_loc,
3681            self.buf.as_ptr() as usize,
3682        ))
3683    }
3684    pub fn get_tuple_master(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3685        let mut iter = self.clone();
3686        iter.pos = 0;
3687        for attr in iter {
3688            if let ConntrackAttrs::TupleMaster(val) = attr? {
3689                return Ok(val);
3690            }
3691        }
3692        Err(ErrorContext::new_missing(
3693            "ConntrackAttrs",
3694            "TupleMaster",
3695            self.orig_loc,
3696            self.buf.as_ptr() as usize,
3697        ))
3698    }
3699    pub fn get_seq_adj_orig(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
3700        let mut iter = self.clone();
3701        iter.pos = 0;
3702        for attr in iter {
3703            if let ConntrackAttrs::SeqAdjOrig(val) = attr? {
3704                return Ok(val);
3705            }
3706        }
3707        Err(ErrorContext::new_missing(
3708            "ConntrackAttrs",
3709            "SeqAdjOrig",
3710            self.orig_loc,
3711            self.buf.as_ptr() as usize,
3712        ))
3713    }
3714    pub fn get_seq_adj_reply(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
3715        let mut iter = self.clone();
3716        iter.pos = 0;
3717        for attr in iter {
3718            if let ConntrackAttrs::SeqAdjReply(val) = attr? {
3719                return Ok(val);
3720            }
3721        }
3722        Err(ErrorContext::new_missing(
3723            "ConntrackAttrs",
3724            "SeqAdjReply",
3725            self.orig_loc,
3726            self.buf.as_ptr() as usize,
3727        ))
3728    }
3729    #[doc = "obsolete"]
3730    pub fn get_secmark(&self) -> Result<&'a [u8], ErrorContext> {
3731        let mut iter = self.clone();
3732        iter.pos = 0;
3733        for attr in iter {
3734            if let ConntrackAttrs::Secmark(val) = attr? {
3735                return Ok(val);
3736            }
3737        }
3738        Err(ErrorContext::new_missing(
3739            "ConntrackAttrs",
3740            "Secmark",
3741            self.orig_loc,
3742            self.buf.as_ptr() as usize,
3743        ))
3744    }
3745    #[doc = "conntrack zone id"]
3746    pub fn get_zone(&self) -> Result<u16, ErrorContext> {
3747        let mut iter = self.clone();
3748        iter.pos = 0;
3749        for attr in iter {
3750            if let ConntrackAttrs::Zone(val) = attr? {
3751                return Ok(val);
3752            }
3753        }
3754        Err(ErrorContext::new_missing(
3755            "ConntrackAttrs",
3756            "Zone",
3757            self.orig_loc,
3758            self.buf.as_ptr() as usize,
3759        ))
3760    }
3761    pub fn get_secctx(&self) -> Result<IterableSecctxAttrs<'a>, ErrorContext> {
3762        let mut iter = self.clone();
3763        iter.pos = 0;
3764        for attr in iter {
3765            if let ConntrackAttrs::Secctx(val) = attr? {
3766                return Ok(val);
3767            }
3768        }
3769        Err(ErrorContext::new_missing(
3770            "ConntrackAttrs",
3771            "Secctx",
3772            self.orig_loc,
3773            self.buf.as_ptr() as usize,
3774        ))
3775    }
3776    pub fn get_timestamp(&self) -> Result<u64, ErrorContext> {
3777        let mut iter = self.clone();
3778        iter.pos = 0;
3779        for attr in iter {
3780            if let ConntrackAttrs::Timestamp(val) = attr? {
3781                return Ok(val);
3782            }
3783        }
3784        Err(ErrorContext::new_missing(
3785            "ConntrackAttrs",
3786            "Timestamp",
3787            self.orig_loc,
3788            self.buf.as_ptr() as usize,
3789        ))
3790    }
3791    pub fn get_mark_mask(&self) -> Result<u32, ErrorContext> {
3792        let mut iter = self.clone();
3793        iter.pos = 0;
3794        for attr in iter {
3795            if let ConntrackAttrs::MarkMask(val) = attr? {
3796                return Ok(val);
3797            }
3798        }
3799        Err(ErrorContext::new_missing(
3800            "ConntrackAttrs",
3801            "MarkMask",
3802            self.orig_loc,
3803            self.buf.as_ptr() as usize,
3804        ))
3805    }
3806    pub fn get_labels(&self) -> Result<&'a [u8], ErrorContext> {
3807        let mut iter = self.clone();
3808        iter.pos = 0;
3809        for attr in iter {
3810            if let ConntrackAttrs::Labels(val) = attr? {
3811                return Ok(val);
3812            }
3813        }
3814        Err(ErrorContext::new_missing(
3815            "ConntrackAttrs",
3816            "Labels",
3817            self.orig_loc,
3818            self.buf.as_ptr() as usize,
3819        ))
3820    }
3821    pub fn get_labels_mask(&self) -> Result<&'a [u8], ErrorContext> {
3822        let mut iter = self.clone();
3823        iter.pos = 0;
3824        for attr in iter {
3825            if let ConntrackAttrs::LabelsMask(val) = attr? {
3826                return Ok(val);
3827            }
3828        }
3829        Err(ErrorContext::new_missing(
3830            "ConntrackAttrs",
3831            "LabelsMask",
3832            self.orig_loc,
3833            self.buf.as_ptr() as usize,
3834        ))
3835    }
3836    pub fn get_synproxy(&self) -> Result<IterableSynproxyAttrs<'a>, ErrorContext> {
3837        let mut iter = self.clone();
3838        iter.pos = 0;
3839        for attr in iter {
3840            if let ConntrackAttrs::Synproxy(val) = attr? {
3841                return Ok(val);
3842            }
3843        }
3844        Err(ErrorContext::new_missing(
3845            "ConntrackAttrs",
3846            "Synproxy",
3847            self.orig_loc,
3848            self.buf.as_ptr() as usize,
3849        ))
3850    }
3851    pub fn get_filter(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3852        let mut iter = self.clone();
3853        iter.pos = 0;
3854        for attr in iter {
3855            if let ConntrackAttrs::Filter(val) = attr? {
3856                return Ok(val);
3857            }
3858        }
3859        Err(ErrorContext::new_missing(
3860            "ConntrackAttrs",
3861            "Filter",
3862            self.orig_loc,
3863            self.buf.as_ptr() as usize,
3864        ))
3865    }
3866    #[doc = "conntrack flag bits to change\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
3867    pub fn get_status_mask(&self) -> Result<u32, ErrorContext> {
3868        let mut iter = self.clone();
3869        iter.pos = 0;
3870        for attr in iter {
3871            if let ConntrackAttrs::StatusMask(val) = attr? {
3872                return Ok(val);
3873            }
3874        }
3875        Err(ErrorContext::new_missing(
3876            "ConntrackAttrs",
3877            "StatusMask",
3878            self.orig_loc,
3879            self.buf.as_ptr() as usize,
3880        ))
3881    }
3882    pub fn get_timestamp_event(&self) -> Result<u64, ErrorContext> {
3883        let mut iter = self.clone();
3884        iter.pos = 0;
3885        for attr in iter {
3886            if let ConntrackAttrs::TimestampEvent(val) = attr? {
3887                return Ok(val);
3888            }
3889        }
3890        Err(ErrorContext::new_missing(
3891            "ConntrackAttrs",
3892            "TimestampEvent",
3893            self.orig_loc,
3894            self.buf.as_ptr() as usize,
3895        ))
3896    }
3897}
3898impl ConntrackAttrs<'_> {
3899    pub fn new<'a>(buf: &'a [u8]) -> IterableConntrackAttrs<'a> {
3900        IterableConntrackAttrs::with_loc(buf, buf.as_ptr() as usize)
3901    }
3902    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3903        let res = match r#type {
3904            1u16 => "TupleOrig",
3905            2u16 => "TupleReply",
3906            3u16 => "Status",
3907            4u16 => "Protoinfo",
3908            5u16 => "Help",
3909            6u16 => "NatSrc",
3910            7u16 => "Timeout",
3911            8u16 => "Mark",
3912            9u16 => "CountersOrig",
3913            10u16 => "CountersReply",
3914            11u16 => "Use",
3915            12u16 => "Id",
3916            13u16 => "NatDst",
3917            14u16 => "TupleMaster",
3918            15u16 => "SeqAdjOrig",
3919            16u16 => "SeqAdjReply",
3920            17u16 => "Secmark",
3921            18u16 => "Zone",
3922            19u16 => "Secctx",
3923            20u16 => "Timestamp",
3924            21u16 => "MarkMask",
3925            22u16 => "Labels",
3926            23u16 => "LabelsMask",
3927            24u16 => "Synproxy",
3928            25u16 => "Filter",
3929            26u16 => "StatusMask",
3930            27u16 => "TimestampEvent",
3931            _ => return None,
3932        };
3933        Some(res)
3934    }
3935}
3936#[derive(Clone, Copy, Default)]
3937pub struct IterableConntrackAttrs<'a> {
3938    buf: &'a [u8],
3939    pos: usize,
3940    orig_loc: usize,
3941}
3942impl<'a> IterableConntrackAttrs<'a> {
3943    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3944        Self {
3945            buf,
3946            pos: 0,
3947            orig_loc,
3948        }
3949    }
3950    pub fn get_buf(&self) -> &'a [u8] {
3951        self.buf
3952    }
3953}
3954impl<'a> Iterator for IterableConntrackAttrs<'a> {
3955    type Item = Result<ConntrackAttrs<'a>, ErrorContext>;
3956    fn next(&mut self) -> Option<Self::Item> {
3957        let pos = self.pos;
3958        let mut r#type;
3959        loop {
3960            r#type = None;
3961            if self.buf.len() == self.pos {
3962                return None;
3963            }
3964            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3965                break;
3966            };
3967            r#type = Some(header.r#type);
3968            let res = match header.r#type {
3969                1u16 => ConntrackAttrs::TupleOrig({
3970                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3971                    let Some(val) = res else { break };
3972                    val
3973                }),
3974                2u16 => ConntrackAttrs::TupleReply({
3975                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3976                    let Some(val) = res else { break };
3977                    val
3978                }),
3979                3u16 => ConntrackAttrs::Status({
3980                    let res = parse_be_u32(next);
3981                    let Some(val) = res else { break };
3982                    val
3983                }),
3984                4u16 => ConntrackAttrs::Protoinfo({
3985                    let res = Some(IterableProtoinfoAttrs::with_loc(next, self.orig_loc));
3986                    let Some(val) = res else { break };
3987                    val
3988                }),
3989                5u16 => ConntrackAttrs::Help({
3990                    let res = Some(IterableHelpAttrs::with_loc(next, self.orig_loc));
3991                    let Some(val) = res else { break };
3992                    val
3993                }),
3994                6u16 => ConntrackAttrs::NatSrc({
3995                    let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
3996                    let Some(val) = res else { break };
3997                    val
3998                }),
3999                7u16 => ConntrackAttrs::Timeout({
4000                    let res = parse_be_u32(next);
4001                    let Some(val) = res else { break };
4002                    val
4003                }),
4004                8u16 => ConntrackAttrs::Mark({
4005                    let res = parse_be_u32(next);
4006                    let Some(val) = res else { break };
4007                    val
4008                }),
4009                9u16 => ConntrackAttrs::CountersOrig({
4010                    let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
4011                    let Some(val) = res else { break };
4012                    val
4013                }),
4014                10u16 => ConntrackAttrs::CountersReply({
4015                    let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
4016                    let Some(val) = res else { break };
4017                    val
4018                }),
4019                11u16 => ConntrackAttrs::Use({
4020                    let res = parse_be_u32(next);
4021                    let Some(val) = res else { break };
4022                    val
4023                }),
4024                12u16 => ConntrackAttrs::Id({
4025                    let res = parse_be_u32(next);
4026                    let Some(val) = res else { break };
4027                    val
4028                }),
4029                13u16 => ConntrackAttrs::NatDst({
4030                    let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
4031                    let Some(val) = res else { break };
4032                    val
4033                }),
4034                14u16 => ConntrackAttrs::TupleMaster({
4035                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
4036                    let Some(val) = res else { break };
4037                    val
4038                }),
4039                15u16 => ConntrackAttrs::SeqAdjOrig({
4040                    let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
4041                    let Some(val) = res else { break };
4042                    val
4043                }),
4044                16u16 => ConntrackAttrs::SeqAdjReply({
4045                    let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
4046                    let Some(val) = res else { break };
4047                    val
4048                }),
4049                17u16 => ConntrackAttrs::Secmark({
4050                    let res = Some(next);
4051                    let Some(val) = res else { break };
4052                    val
4053                }),
4054                18u16 => ConntrackAttrs::Zone({
4055                    let res = parse_be_u16(next);
4056                    let Some(val) = res else { break };
4057                    val
4058                }),
4059                19u16 => ConntrackAttrs::Secctx({
4060                    let res = Some(IterableSecctxAttrs::with_loc(next, self.orig_loc));
4061                    let Some(val) = res else { break };
4062                    val
4063                }),
4064                20u16 => ConntrackAttrs::Timestamp({
4065                    let res = parse_be_u64(next);
4066                    let Some(val) = res else { break };
4067                    val
4068                }),
4069                21u16 => ConntrackAttrs::MarkMask({
4070                    let res = parse_be_u32(next);
4071                    let Some(val) = res else { break };
4072                    val
4073                }),
4074                22u16 => ConntrackAttrs::Labels({
4075                    let res = Some(next);
4076                    let Some(val) = res else { break };
4077                    val
4078                }),
4079                23u16 => ConntrackAttrs::LabelsMask({
4080                    let res = Some(next);
4081                    let Some(val) = res else { break };
4082                    val
4083                }),
4084                24u16 => ConntrackAttrs::Synproxy({
4085                    let res = Some(IterableSynproxyAttrs::with_loc(next, self.orig_loc));
4086                    let Some(val) = res else { break };
4087                    val
4088                }),
4089                25u16 => ConntrackAttrs::Filter({
4090                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
4091                    let Some(val) = res else { break };
4092                    val
4093                }),
4094                26u16 => ConntrackAttrs::StatusMask({
4095                    let res = parse_be_u32(next);
4096                    let Some(val) = res else { break };
4097                    val
4098                }),
4099                27u16 => ConntrackAttrs::TimestampEvent({
4100                    let res = parse_be_u64(next);
4101                    let Some(val) = res else { break };
4102                    val
4103                }),
4104                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
4105                n => continue,
4106            };
4107            return Some(Ok(res));
4108        }
4109        Some(Err(ErrorContext::new(
4110            "ConntrackAttrs",
4111            r#type.and_then(|t| ConntrackAttrs::attr_from_type(t)),
4112            self.orig_loc,
4113            self.buf.as_ptr().wrapping_add(pos) as usize,
4114        )))
4115    }
4116}
4117impl<'a> std::fmt::Debug for IterableConntrackAttrs<'_> {
4118    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4119        let mut fmt = f.debug_struct("ConntrackAttrs");
4120        for attr in self.clone() {
4121            let attr = match attr {
4122                Ok(a) => a,
4123                Err(err) => {
4124                    fmt.finish()?;
4125                    f.write_str("Err(")?;
4126                    err.fmt(f)?;
4127                    return f.write_str(")");
4128                }
4129            };
4130            match attr {
4131                ConntrackAttrs::TupleOrig(val) => fmt.field("TupleOrig", &val),
4132                ConntrackAttrs::TupleReply(val) => fmt.field("TupleReply", &val),
4133                ConntrackAttrs::Status(val) => {
4134                    fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
4135                }
4136                ConntrackAttrs::Protoinfo(val) => fmt.field("Protoinfo", &val),
4137                ConntrackAttrs::Help(val) => fmt.field("Help", &val),
4138                ConntrackAttrs::NatSrc(val) => fmt.field("NatSrc", &val),
4139                ConntrackAttrs::Timeout(val) => fmt.field("Timeout", &val),
4140                ConntrackAttrs::Mark(val) => fmt.field("Mark", &val),
4141                ConntrackAttrs::CountersOrig(val) => fmt.field("CountersOrig", &val),
4142                ConntrackAttrs::CountersReply(val) => fmt.field("CountersReply", &val),
4143                ConntrackAttrs::Use(val) => fmt.field("Use", &val),
4144                ConntrackAttrs::Id(val) => fmt.field("Id", &val),
4145                ConntrackAttrs::NatDst(val) => fmt.field("NatDst", &val),
4146                ConntrackAttrs::TupleMaster(val) => fmt.field("TupleMaster", &val),
4147                ConntrackAttrs::SeqAdjOrig(val) => fmt.field("SeqAdjOrig", &val),
4148                ConntrackAttrs::SeqAdjReply(val) => fmt.field("SeqAdjReply", &val),
4149                ConntrackAttrs::Secmark(val) => fmt.field("Secmark", &val),
4150                ConntrackAttrs::Zone(val) => fmt.field("Zone", &val),
4151                ConntrackAttrs::Secctx(val) => fmt.field("Secctx", &val),
4152                ConntrackAttrs::Timestamp(val) => fmt.field("Timestamp", &val),
4153                ConntrackAttrs::MarkMask(val) => fmt.field("MarkMask", &val),
4154                ConntrackAttrs::Labels(val) => fmt.field("Labels", &val),
4155                ConntrackAttrs::LabelsMask(val) => fmt.field("LabelsMask", &val),
4156                ConntrackAttrs::Synproxy(val) => fmt.field("Synproxy", &val),
4157                ConntrackAttrs::Filter(val) => fmt.field("Filter", &val),
4158                ConntrackAttrs::StatusMask(val) => fmt.field(
4159                    "StatusMask",
4160                    &FormatFlags(val.into(), NfCtStatus::from_value),
4161                ),
4162                ConntrackAttrs::TimestampEvent(val) => fmt.field("TimestampEvent", &val),
4163            };
4164        }
4165        fmt.finish()
4166    }
4167}
4168impl IterableConntrackAttrs<'_> {
4169    pub fn lookup_attr(
4170        &self,
4171        offset: usize,
4172        missing_type: Option<u16>,
4173    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4174        let mut stack = Vec::new();
4175        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4176        if missing_type.is_some() && cur == offset {
4177            stack.push(("ConntrackAttrs", offset));
4178            return (
4179                stack,
4180                missing_type.and_then(|t| ConntrackAttrs::attr_from_type(t)),
4181            );
4182        }
4183        if cur > offset || cur + self.buf.len() < offset {
4184            return (stack, None);
4185        }
4186        let mut attrs = self.clone();
4187        let mut last_off = cur + attrs.pos;
4188        let mut missing = None;
4189        while let Some(attr) = attrs.next() {
4190            let Ok(attr) = attr else { break };
4191            match attr {
4192                ConntrackAttrs::TupleOrig(val) => {
4193                    (stack, missing) = val.lookup_attr(offset, missing_type);
4194                    if !stack.is_empty() {
4195                        break;
4196                    }
4197                }
4198                ConntrackAttrs::TupleReply(val) => {
4199                    (stack, missing) = val.lookup_attr(offset, missing_type);
4200                    if !stack.is_empty() {
4201                        break;
4202                    }
4203                }
4204                ConntrackAttrs::Status(val) => {
4205                    if last_off == offset {
4206                        stack.push(("Status", last_off));
4207                        break;
4208                    }
4209                }
4210                ConntrackAttrs::Protoinfo(val) => {
4211                    (stack, missing) = val.lookup_attr(offset, missing_type);
4212                    if !stack.is_empty() {
4213                        break;
4214                    }
4215                }
4216                ConntrackAttrs::Help(val) => {
4217                    (stack, missing) = val.lookup_attr(offset, missing_type);
4218                    if !stack.is_empty() {
4219                        break;
4220                    }
4221                }
4222                ConntrackAttrs::NatSrc(val) => {
4223                    (stack, missing) = val.lookup_attr(offset, missing_type);
4224                    if !stack.is_empty() {
4225                        break;
4226                    }
4227                }
4228                ConntrackAttrs::Timeout(val) => {
4229                    if last_off == offset {
4230                        stack.push(("Timeout", last_off));
4231                        break;
4232                    }
4233                }
4234                ConntrackAttrs::Mark(val) => {
4235                    if last_off == offset {
4236                        stack.push(("Mark", last_off));
4237                        break;
4238                    }
4239                }
4240                ConntrackAttrs::CountersOrig(val) => {
4241                    (stack, missing) = val.lookup_attr(offset, missing_type);
4242                    if !stack.is_empty() {
4243                        break;
4244                    }
4245                }
4246                ConntrackAttrs::CountersReply(val) => {
4247                    (stack, missing) = val.lookup_attr(offset, missing_type);
4248                    if !stack.is_empty() {
4249                        break;
4250                    }
4251                }
4252                ConntrackAttrs::Use(val) => {
4253                    if last_off == offset {
4254                        stack.push(("Use", last_off));
4255                        break;
4256                    }
4257                }
4258                ConntrackAttrs::Id(val) => {
4259                    if last_off == offset {
4260                        stack.push(("Id", last_off));
4261                        break;
4262                    }
4263                }
4264                ConntrackAttrs::NatDst(val) => {
4265                    (stack, missing) = val.lookup_attr(offset, missing_type);
4266                    if !stack.is_empty() {
4267                        break;
4268                    }
4269                }
4270                ConntrackAttrs::TupleMaster(val) => {
4271                    (stack, missing) = val.lookup_attr(offset, missing_type);
4272                    if !stack.is_empty() {
4273                        break;
4274                    }
4275                }
4276                ConntrackAttrs::SeqAdjOrig(val) => {
4277                    (stack, missing) = val.lookup_attr(offset, missing_type);
4278                    if !stack.is_empty() {
4279                        break;
4280                    }
4281                }
4282                ConntrackAttrs::SeqAdjReply(val) => {
4283                    (stack, missing) = val.lookup_attr(offset, missing_type);
4284                    if !stack.is_empty() {
4285                        break;
4286                    }
4287                }
4288                ConntrackAttrs::Secmark(val) => {
4289                    if last_off == offset {
4290                        stack.push(("Secmark", last_off));
4291                        break;
4292                    }
4293                }
4294                ConntrackAttrs::Zone(val) => {
4295                    if last_off == offset {
4296                        stack.push(("Zone", last_off));
4297                        break;
4298                    }
4299                }
4300                ConntrackAttrs::Secctx(val) => {
4301                    (stack, missing) = val.lookup_attr(offset, missing_type);
4302                    if !stack.is_empty() {
4303                        break;
4304                    }
4305                }
4306                ConntrackAttrs::Timestamp(val) => {
4307                    if last_off == offset {
4308                        stack.push(("Timestamp", last_off));
4309                        break;
4310                    }
4311                }
4312                ConntrackAttrs::MarkMask(val) => {
4313                    if last_off == offset {
4314                        stack.push(("MarkMask", last_off));
4315                        break;
4316                    }
4317                }
4318                ConntrackAttrs::Labels(val) => {
4319                    if last_off == offset {
4320                        stack.push(("Labels", last_off));
4321                        break;
4322                    }
4323                }
4324                ConntrackAttrs::LabelsMask(val) => {
4325                    if last_off == offset {
4326                        stack.push(("LabelsMask", last_off));
4327                        break;
4328                    }
4329                }
4330                ConntrackAttrs::Synproxy(val) => {
4331                    (stack, missing) = val.lookup_attr(offset, missing_type);
4332                    if !stack.is_empty() {
4333                        break;
4334                    }
4335                }
4336                ConntrackAttrs::Filter(val) => {
4337                    (stack, missing) = val.lookup_attr(offset, missing_type);
4338                    if !stack.is_empty() {
4339                        break;
4340                    }
4341                }
4342                ConntrackAttrs::StatusMask(val) => {
4343                    if last_off == offset {
4344                        stack.push(("StatusMask", last_off));
4345                        break;
4346                    }
4347                }
4348                ConntrackAttrs::TimestampEvent(val) => {
4349                    if last_off == offset {
4350                        stack.push(("TimestampEvent", last_off));
4351                        break;
4352                    }
4353                }
4354                _ => {}
4355            };
4356            last_off = cur + attrs.pos;
4357        }
4358        if !stack.is_empty() {
4359            stack.push(("ConntrackAttrs", cur));
4360        }
4361        (stack, missing)
4362    }
4363}
4364#[derive(Clone)]
4365pub enum ConntrackStatsAttrs {
4366    #[doc = "obsolete"]
4367    Searched(u32),
4368    Found(u32),
4369    #[doc = "obsolete"]
4370    New(u32),
4371    #[doc = "obsolete"]
4372    Invalid(u32),
4373    #[doc = "obsolete"]
4374    Ignore(u32),
4375    #[doc = "obsolete"]
4376    Delete(u32),
4377    #[doc = "obsolete"]
4378    DeleteList(u32),
4379    Insert(u32),
4380    InsertFailed(u32),
4381    Drop(u32),
4382    EarlyDrop(u32),
4383    Error(u32),
4384    SearchRestart(u32),
4385    ClashResolve(u32),
4386    ChainToolong(u32),
4387}
4388impl<'a> IterableConntrackStatsAttrs<'a> {
4389    #[doc = "obsolete"]
4390    pub fn get_searched(&self) -> Result<u32, ErrorContext> {
4391        let mut iter = self.clone();
4392        iter.pos = 0;
4393        for attr in iter {
4394            if let ConntrackStatsAttrs::Searched(val) = attr? {
4395                return Ok(val);
4396            }
4397        }
4398        Err(ErrorContext::new_missing(
4399            "ConntrackStatsAttrs",
4400            "Searched",
4401            self.orig_loc,
4402            self.buf.as_ptr() as usize,
4403        ))
4404    }
4405    pub fn get_found(&self) -> Result<u32, ErrorContext> {
4406        let mut iter = self.clone();
4407        iter.pos = 0;
4408        for attr in iter {
4409            if let ConntrackStatsAttrs::Found(val) = attr? {
4410                return Ok(val);
4411            }
4412        }
4413        Err(ErrorContext::new_missing(
4414            "ConntrackStatsAttrs",
4415            "Found",
4416            self.orig_loc,
4417            self.buf.as_ptr() as usize,
4418        ))
4419    }
4420    #[doc = "obsolete"]
4421    pub fn get_new(&self) -> Result<u32, ErrorContext> {
4422        let mut iter = self.clone();
4423        iter.pos = 0;
4424        for attr in iter {
4425            if let ConntrackStatsAttrs::New(val) = attr? {
4426                return Ok(val);
4427            }
4428        }
4429        Err(ErrorContext::new_missing(
4430            "ConntrackStatsAttrs",
4431            "New",
4432            self.orig_loc,
4433            self.buf.as_ptr() as usize,
4434        ))
4435    }
4436    #[doc = "obsolete"]
4437    pub fn get_invalid(&self) -> Result<u32, ErrorContext> {
4438        let mut iter = self.clone();
4439        iter.pos = 0;
4440        for attr in iter {
4441            if let ConntrackStatsAttrs::Invalid(val) = attr? {
4442                return Ok(val);
4443            }
4444        }
4445        Err(ErrorContext::new_missing(
4446            "ConntrackStatsAttrs",
4447            "Invalid",
4448            self.orig_loc,
4449            self.buf.as_ptr() as usize,
4450        ))
4451    }
4452    #[doc = "obsolete"]
4453    pub fn get_ignore(&self) -> Result<u32, ErrorContext> {
4454        let mut iter = self.clone();
4455        iter.pos = 0;
4456        for attr in iter {
4457            if let ConntrackStatsAttrs::Ignore(val) = attr? {
4458                return Ok(val);
4459            }
4460        }
4461        Err(ErrorContext::new_missing(
4462            "ConntrackStatsAttrs",
4463            "Ignore",
4464            self.orig_loc,
4465            self.buf.as_ptr() as usize,
4466        ))
4467    }
4468    #[doc = "obsolete"]
4469    pub fn get_delete(&self) -> Result<u32, ErrorContext> {
4470        let mut iter = self.clone();
4471        iter.pos = 0;
4472        for attr in iter {
4473            if let ConntrackStatsAttrs::Delete(val) = attr? {
4474                return Ok(val);
4475            }
4476        }
4477        Err(ErrorContext::new_missing(
4478            "ConntrackStatsAttrs",
4479            "Delete",
4480            self.orig_loc,
4481            self.buf.as_ptr() as usize,
4482        ))
4483    }
4484    #[doc = "obsolete"]
4485    pub fn get_delete_list(&self) -> Result<u32, ErrorContext> {
4486        let mut iter = self.clone();
4487        iter.pos = 0;
4488        for attr in iter {
4489            if let ConntrackStatsAttrs::DeleteList(val) = attr? {
4490                return Ok(val);
4491            }
4492        }
4493        Err(ErrorContext::new_missing(
4494            "ConntrackStatsAttrs",
4495            "DeleteList",
4496            self.orig_loc,
4497            self.buf.as_ptr() as usize,
4498        ))
4499    }
4500    pub fn get_insert(&self) -> Result<u32, ErrorContext> {
4501        let mut iter = self.clone();
4502        iter.pos = 0;
4503        for attr in iter {
4504            if let ConntrackStatsAttrs::Insert(val) = attr? {
4505                return Ok(val);
4506            }
4507        }
4508        Err(ErrorContext::new_missing(
4509            "ConntrackStatsAttrs",
4510            "Insert",
4511            self.orig_loc,
4512            self.buf.as_ptr() as usize,
4513        ))
4514    }
4515    pub fn get_insert_failed(&self) -> Result<u32, ErrorContext> {
4516        let mut iter = self.clone();
4517        iter.pos = 0;
4518        for attr in iter {
4519            if let ConntrackStatsAttrs::InsertFailed(val) = attr? {
4520                return Ok(val);
4521            }
4522        }
4523        Err(ErrorContext::new_missing(
4524            "ConntrackStatsAttrs",
4525            "InsertFailed",
4526            self.orig_loc,
4527            self.buf.as_ptr() as usize,
4528        ))
4529    }
4530    pub fn get_drop(&self) -> Result<u32, ErrorContext> {
4531        let mut iter = self.clone();
4532        iter.pos = 0;
4533        for attr in iter {
4534            if let ConntrackStatsAttrs::Drop(val) = attr? {
4535                return Ok(val);
4536            }
4537        }
4538        Err(ErrorContext::new_missing(
4539            "ConntrackStatsAttrs",
4540            "Drop",
4541            self.orig_loc,
4542            self.buf.as_ptr() as usize,
4543        ))
4544    }
4545    pub fn get_early_drop(&self) -> Result<u32, ErrorContext> {
4546        let mut iter = self.clone();
4547        iter.pos = 0;
4548        for attr in iter {
4549            if let ConntrackStatsAttrs::EarlyDrop(val) = attr? {
4550                return Ok(val);
4551            }
4552        }
4553        Err(ErrorContext::new_missing(
4554            "ConntrackStatsAttrs",
4555            "EarlyDrop",
4556            self.orig_loc,
4557            self.buf.as_ptr() as usize,
4558        ))
4559    }
4560    pub fn get_error(&self) -> Result<u32, ErrorContext> {
4561        let mut iter = self.clone();
4562        iter.pos = 0;
4563        for attr in iter {
4564            if let ConntrackStatsAttrs::Error(val) = attr? {
4565                return Ok(val);
4566            }
4567        }
4568        Err(ErrorContext::new_missing(
4569            "ConntrackStatsAttrs",
4570            "Error",
4571            self.orig_loc,
4572            self.buf.as_ptr() as usize,
4573        ))
4574    }
4575    pub fn get_search_restart(&self) -> Result<u32, ErrorContext> {
4576        let mut iter = self.clone();
4577        iter.pos = 0;
4578        for attr in iter {
4579            if let ConntrackStatsAttrs::SearchRestart(val) = attr? {
4580                return Ok(val);
4581            }
4582        }
4583        Err(ErrorContext::new_missing(
4584            "ConntrackStatsAttrs",
4585            "SearchRestart",
4586            self.orig_loc,
4587            self.buf.as_ptr() as usize,
4588        ))
4589    }
4590    pub fn get_clash_resolve(&self) -> Result<u32, ErrorContext> {
4591        let mut iter = self.clone();
4592        iter.pos = 0;
4593        for attr in iter {
4594            if let ConntrackStatsAttrs::ClashResolve(val) = attr? {
4595                return Ok(val);
4596            }
4597        }
4598        Err(ErrorContext::new_missing(
4599            "ConntrackStatsAttrs",
4600            "ClashResolve",
4601            self.orig_loc,
4602            self.buf.as_ptr() as usize,
4603        ))
4604    }
4605    pub fn get_chain_toolong(&self) -> Result<u32, ErrorContext> {
4606        let mut iter = self.clone();
4607        iter.pos = 0;
4608        for attr in iter {
4609            if let ConntrackStatsAttrs::ChainToolong(val) = attr? {
4610                return Ok(val);
4611            }
4612        }
4613        Err(ErrorContext::new_missing(
4614            "ConntrackStatsAttrs",
4615            "ChainToolong",
4616            self.orig_loc,
4617            self.buf.as_ptr() as usize,
4618        ))
4619    }
4620}
4621impl ConntrackStatsAttrs {
4622    pub fn new<'a>(buf: &'a [u8]) -> IterableConntrackStatsAttrs<'a> {
4623        IterableConntrackStatsAttrs::with_loc(buf, buf.as_ptr() as usize)
4624    }
4625    fn attr_from_type(r#type: u16) -> Option<&'static str> {
4626        let res = match r#type {
4627            1u16 => "Searched",
4628            2u16 => "Found",
4629            3u16 => "New",
4630            4u16 => "Invalid",
4631            5u16 => "Ignore",
4632            6u16 => "Delete",
4633            7u16 => "DeleteList",
4634            8u16 => "Insert",
4635            9u16 => "InsertFailed",
4636            10u16 => "Drop",
4637            11u16 => "EarlyDrop",
4638            12u16 => "Error",
4639            13u16 => "SearchRestart",
4640            14u16 => "ClashResolve",
4641            15u16 => "ChainToolong",
4642            _ => return None,
4643        };
4644        Some(res)
4645    }
4646}
4647#[derive(Clone, Copy, Default)]
4648pub struct IterableConntrackStatsAttrs<'a> {
4649    buf: &'a [u8],
4650    pos: usize,
4651    orig_loc: usize,
4652}
4653impl<'a> IterableConntrackStatsAttrs<'a> {
4654    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4655        Self {
4656            buf,
4657            pos: 0,
4658            orig_loc,
4659        }
4660    }
4661    pub fn get_buf(&self) -> &'a [u8] {
4662        self.buf
4663    }
4664}
4665impl<'a> Iterator for IterableConntrackStatsAttrs<'a> {
4666    type Item = Result<ConntrackStatsAttrs, ErrorContext>;
4667    fn next(&mut self) -> Option<Self::Item> {
4668        let pos = self.pos;
4669        let mut r#type;
4670        loop {
4671            r#type = None;
4672            if self.buf.len() == self.pos {
4673                return None;
4674            }
4675            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
4676                break;
4677            };
4678            r#type = Some(header.r#type);
4679            let res = match header.r#type {
4680                1u16 => ConntrackStatsAttrs::Searched({
4681                    let res = parse_be_u32(next);
4682                    let Some(val) = res else { break };
4683                    val
4684                }),
4685                2u16 => ConntrackStatsAttrs::Found({
4686                    let res = parse_be_u32(next);
4687                    let Some(val) = res else { break };
4688                    val
4689                }),
4690                3u16 => ConntrackStatsAttrs::New({
4691                    let res = parse_be_u32(next);
4692                    let Some(val) = res else { break };
4693                    val
4694                }),
4695                4u16 => ConntrackStatsAttrs::Invalid({
4696                    let res = parse_be_u32(next);
4697                    let Some(val) = res else { break };
4698                    val
4699                }),
4700                5u16 => ConntrackStatsAttrs::Ignore({
4701                    let res = parse_be_u32(next);
4702                    let Some(val) = res else { break };
4703                    val
4704                }),
4705                6u16 => ConntrackStatsAttrs::Delete({
4706                    let res = parse_be_u32(next);
4707                    let Some(val) = res else { break };
4708                    val
4709                }),
4710                7u16 => ConntrackStatsAttrs::DeleteList({
4711                    let res = parse_be_u32(next);
4712                    let Some(val) = res else { break };
4713                    val
4714                }),
4715                8u16 => ConntrackStatsAttrs::Insert({
4716                    let res = parse_be_u32(next);
4717                    let Some(val) = res else { break };
4718                    val
4719                }),
4720                9u16 => ConntrackStatsAttrs::InsertFailed({
4721                    let res = parse_be_u32(next);
4722                    let Some(val) = res else { break };
4723                    val
4724                }),
4725                10u16 => ConntrackStatsAttrs::Drop({
4726                    let res = parse_be_u32(next);
4727                    let Some(val) = res else { break };
4728                    val
4729                }),
4730                11u16 => ConntrackStatsAttrs::EarlyDrop({
4731                    let res = parse_be_u32(next);
4732                    let Some(val) = res else { break };
4733                    val
4734                }),
4735                12u16 => ConntrackStatsAttrs::Error({
4736                    let res = parse_be_u32(next);
4737                    let Some(val) = res else { break };
4738                    val
4739                }),
4740                13u16 => ConntrackStatsAttrs::SearchRestart({
4741                    let res = parse_be_u32(next);
4742                    let Some(val) = res else { break };
4743                    val
4744                }),
4745                14u16 => ConntrackStatsAttrs::ClashResolve({
4746                    let res = parse_be_u32(next);
4747                    let Some(val) = res else { break };
4748                    val
4749                }),
4750                15u16 => ConntrackStatsAttrs::ChainToolong({
4751                    let res = parse_be_u32(next);
4752                    let Some(val) = res else { break };
4753                    val
4754                }),
4755                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
4756                n => continue,
4757            };
4758            return Some(Ok(res));
4759        }
4760        Some(Err(ErrorContext::new(
4761            "ConntrackStatsAttrs",
4762            r#type.and_then(|t| ConntrackStatsAttrs::attr_from_type(t)),
4763            self.orig_loc,
4764            self.buf.as_ptr().wrapping_add(pos) as usize,
4765        )))
4766    }
4767}
4768impl std::fmt::Debug for IterableConntrackStatsAttrs<'_> {
4769    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4770        let mut fmt = f.debug_struct("ConntrackStatsAttrs");
4771        for attr in self.clone() {
4772            let attr = match attr {
4773                Ok(a) => a,
4774                Err(err) => {
4775                    fmt.finish()?;
4776                    f.write_str("Err(")?;
4777                    err.fmt(f)?;
4778                    return f.write_str(")");
4779                }
4780            };
4781            match attr {
4782                ConntrackStatsAttrs::Searched(val) => fmt.field("Searched", &val),
4783                ConntrackStatsAttrs::Found(val) => fmt.field("Found", &val),
4784                ConntrackStatsAttrs::New(val) => fmt.field("New", &val),
4785                ConntrackStatsAttrs::Invalid(val) => fmt.field("Invalid", &val),
4786                ConntrackStatsAttrs::Ignore(val) => fmt.field("Ignore", &val),
4787                ConntrackStatsAttrs::Delete(val) => fmt.field("Delete", &val),
4788                ConntrackStatsAttrs::DeleteList(val) => fmt.field("DeleteList", &val),
4789                ConntrackStatsAttrs::Insert(val) => fmt.field("Insert", &val),
4790                ConntrackStatsAttrs::InsertFailed(val) => fmt.field("InsertFailed", &val),
4791                ConntrackStatsAttrs::Drop(val) => fmt.field("Drop", &val),
4792                ConntrackStatsAttrs::EarlyDrop(val) => fmt.field("EarlyDrop", &val),
4793                ConntrackStatsAttrs::Error(val) => fmt.field("Error", &val),
4794                ConntrackStatsAttrs::SearchRestart(val) => fmt.field("SearchRestart", &val),
4795                ConntrackStatsAttrs::ClashResolve(val) => fmt.field("ClashResolve", &val),
4796                ConntrackStatsAttrs::ChainToolong(val) => fmt.field("ChainToolong", &val),
4797            };
4798        }
4799        fmt.finish()
4800    }
4801}
4802impl IterableConntrackStatsAttrs<'_> {
4803    pub fn lookup_attr(
4804        &self,
4805        offset: usize,
4806        missing_type: Option<u16>,
4807    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4808        let mut stack = Vec::new();
4809        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4810        if missing_type.is_some() && cur == offset {
4811            stack.push(("ConntrackStatsAttrs", offset));
4812            return (
4813                stack,
4814                missing_type.and_then(|t| ConntrackStatsAttrs::attr_from_type(t)),
4815            );
4816        }
4817        if cur > offset || cur + self.buf.len() < offset {
4818            return (stack, None);
4819        }
4820        let mut attrs = self.clone();
4821        let mut last_off = cur + attrs.pos;
4822        while let Some(attr) = attrs.next() {
4823            let Ok(attr) = attr else { break };
4824            match attr {
4825                ConntrackStatsAttrs::Searched(val) => {
4826                    if last_off == offset {
4827                        stack.push(("Searched", last_off));
4828                        break;
4829                    }
4830                }
4831                ConntrackStatsAttrs::Found(val) => {
4832                    if last_off == offset {
4833                        stack.push(("Found", last_off));
4834                        break;
4835                    }
4836                }
4837                ConntrackStatsAttrs::New(val) => {
4838                    if last_off == offset {
4839                        stack.push(("New", last_off));
4840                        break;
4841                    }
4842                }
4843                ConntrackStatsAttrs::Invalid(val) => {
4844                    if last_off == offset {
4845                        stack.push(("Invalid", last_off));
4846                        break;
4847                    }
4848                }
4849                ConntrackStatsAttrs::Ignore(val) => {
4850                    if last_off == offset {
4851                        stack.push(("Ignore", last_off));
4852                        break;
4853                    }
4854                }
4855                ConntrackStatsAttrs::Delete(val) => {
4856                    if last_off == offset {
4857                        stack.push(("Delete", last_off));
4858                        break;
4859                    }
4860                }
4861                ConntrackStatsAttrs::DeleteList(val) => {
4862                    if last_off == offset {
4863                        stack.push(("DeleteList", last_off));
4864                        break;
4865                    }
4866                }
4867                ConntrackStatsAttrs::Insert(val) => {
4868                    if last_off == offset {
4869                        stack.push(("Insert", last_off));
4870                        break;
4871                    }
4872                }
4873                ConntrackStatsAttrs::InsertFailed(val) => {
4874                    if last_off == offset {
4875                        stack.push(("InsertFailed", last_off));
4876                        break;
4877                    }
4878                }
4879                ConntrackStatsAttrs::Drop(val) => {
4880                    if last_off == offset {
4881                        stack.push(("Drop", last_off));
4882                        break;
4883                    }
4884                }
4885                ConntrackStatsAttrs::EarlyDrop(val) => {
4886                    if last_off == offset {
4887                        stack.push(("EarlyDrop", last_off));
4888                        break;
4889                    }
4890                }
4891                ConntrackStatsAttrs::Error(val) => {
4892                    if last_off == offset {
4893                        stack.push(("Error", last_off));
4894                        break;
4895                    }
4896                }
4897                ConntrackStatsAttrs::SearchRestart(val) => {
4898                    if last_off == offset {
4899                        stack.push(("SearchRestart", last_off));
4900                        break;
4901                    }
4902                }
4903                ConntrackStatsAttrs::ClashResolve(val) => {
4904                    if last_off == offset {
4905                        stack.push(("ClashResolve", last_off));
4906                        break;
4907                    }
4908                }
4909                ConntrackStatsAttrs::ChainToolong(val) => {
4910                    if last_off == offset {
4911                        stack.push(("ChainToolong", last_off));
4912                        break;
4913                    }
4914                }
4915                _ => {}
4916            };
4917            last_off = cur + attrs.pos;
4918        }
4919        if !stack.is_empty() {
4920            stack.push(("ConntrackStatsAttrs", cur));
4921        }
4922        (stack, None)
4923    }
4924}
4925pub struct PushCounterAttrs<Prev: Rec> {
4926    pub(crate) prev: Option<Prev>,
4927    pub(crate) header_offset: Option<usize>,
4928}
4929impl<Prev: Rec> Rec for PushCounterAttrs<Prev> {
4930    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4931        self.prev.as_mut().unwrap().as_rec_mut()
4932    }
4933    fn as_rec(&self) -> &Vec<u8> {
4934        self.prev.as_ref().unwrap().as_rec()
4935    }
4936}
4937impl<Prev: Rec> PushCounterAttrs<Prev> {
4938    pub fn new(prev: Prev) -> Self {
4939        Self {
4940            prev: Some(prev),
4941            header_offset: None,
4942        }
4943    }
4944    pub fn end_nested(mut self) -> Prev {
4945        let mut prev = self.prev.take().unwrap();
4946        if let Some(header_offset) = &self.header_offset {
4947            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4948        }
4949        prev
4950    }
4951    pub fn push_packets(mut self, value: u64) -> Self {
4952        push_header(self.as_rec_mut(), 1u16, 8 as u16);
4953        self.as_rec_mut().extend(value.to_be_bytes());
4954        self
4955    }
4956    pub fn push_bytes(mut self, value: u64) -> Self {
4957        push_header(self.as_rec_mut(), 2u16, 8 as u16);
4958        self.as_rec_mut().extend(value.to_be_bytes());
4959        self
4960    }
4961    pub fn push_packets_old(mut self, value: u32) -> Self {
4962        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4963        self.as_rec_mut().extend(value.to_ne_bytes());
4964        self
4965    }
4966    pub fn push_bytes_old(mut self, value: u32) -> Self {
4967        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4968        self.as_rec_mut().extend(value.to_ne_bytes());
4969        self
4970    }
4971    pub fn push_pad(mut self, value: &[u8]) -> Self {
4972        push_header(self.as_rec_mut(), 5u16, value.len() as u16);
4973        self.as_rec_mut().extend(value);
4974        self
4975    }
4976}
4977impl<Prev: Rec> Drop for PushCounterAttrs<Prev> {
4978    fn drop(&mut self) {
4979        if let Some(prev) = &mut self.prev {
4980            if let Some(header_offset) = &self.header_offset {
4981                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4982            }
4983        }
4984    }
4985}
4986pub struct PushTupleProtoAttrs<Prev: Rec> {
4987    pub(crate) prev: Option<Prev>,
4988    pub(crate) header_offset: Option<usize>,
4989}
4990impl<Prev: Rec> Rec for PushTupleProtoAttrs<Prev> {
4991    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4992        self.prev.as_mut().unwrap().as_rec_mut()
4993    }
4994    fn as_rec(&self) -> &Vec<u8> {
4995        self.prev.as_ref().unwrap().as_rec()
4996    }
4997}
4998impl<Prev: Rec> PushTupleProtoAttrs<Prev> {
4999    pub fn new(prev: Prev) -> Self {
5000        Self {
5001            prev: Some(prev),
5002            header_offset: None,
5003        }
5004    }
5005    pub fn end_nested(mut self) -> Prev {
5006        let mut prev = self.prev.take().unwrap();
5007        if let Some(header_offset) = &self.header_offset {
5008            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5009        }
5010        prev
5011    }
5012    #[doc = "l4 protocol number"]
5013    pub fn push_proto_num(mut self, value: u8) -> Self {
5014        push_header(self.as_rec_mut(), 1u16, 1 as u16);
5015        self.as_rec_mut().extend(value.to_ne_bytes());
5016        self
5017    }
5018    #[doc = "l4 source port"]
5019    pub fn push_proto_src_port(mut self, value: u16) -> Self {
5020        push_header(self.as_rec_mut(), 2u16, 2 as u16);
5021        self.as_rec_mut().extend(value.to_be_bytes());
5022        self
5023    }
5024    #[doc = "l4 source port"]
5025    pub fn push_proto_dst_port(mut self, value: u16) -> Self {
5026        push_header(self.as_rec_mut(), 3u16, 2 as u16);
5027        self.as_rec_mut().extend(value.to_be_bytes());
5028        self
5029    }
5030    #[doc = "l4 icmp id"]
5031    pub fn push_proto_icmp_id(mut self, value: u16) -> Self {
5032        push_header(self.as_rec_mut(), 4u16, 2 as u16);
5033        self.as_rec_mut().extend(value.to_be_bytes());
5034        self
5035    }
5036    pub fn push_proto_icmp_type(mut self, value: u8) -> Self {
5037        push_header(self.as_rec_mut(), 5u16, 1 as u16);
5038        self.as_rec_mut().extend(value.to_ne_bytes());
5039        self
5040    }
5041    pub fn push_proto_icmp_code(mut self, value: u8) -> Self {
5042        push_header(self.as_rec_mut(), 6u16, 1 as u16);
5043        self.as_rec_mut().extend(value.to_ne_bytes());
5044        self
5045    }
5046    #[doc = "l4 icmp id"]
5047    pub fn push_proto_icmpv6_id(mut self, value: u16) -> Self {
5048        push_header(self.as_rec_mut(), 7u16, 2 as u16);
5049        self.as_rec_mut().extend(value.to_be_bytes());
5050        self
5051    }
5052    pub fn push_proto_icmpv6_type(mut self, value: u8) -> Self {
5053        push_header(self.as_rec_mut(), 8u16, 1 as u16);
5054        self.as_rec_mut().extend(value.to_ne_bytes());
5055        self
5056    }
5057    pub fn push_proto_icmpv6_code(mut self, value: u8) -> Self {
5058        push_header(self.as_rec_mut(), 9u16, 1 as u16);
5059        self.as_rec_mut().extend(value.to_ne_bytes());
5060        self
5061    }
5062}
5063impl<Prev: Rec> Drop for PushTupleProtoAttrs<Prev> {
5064    fn drop(&mut self) {
5065        if let Some(prev) = &mut self.prev {
5066            if let Some(header_offset) = &self.header_offset {
5067                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5068            }
5069        }
5070    }
5071}
5072pub struct PushTupleIpAttrs<Prev: Rec> {
5073    pub(crate) prev: Option<Prev>,
5074    pub(crate) header_offset: Option<usize>,
5075}
5076impl<Prev: Rec> Rec for PushTupleIpAttrs<Prev> {
5077    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5078        self.prev.as_mut().unwrap().as_rec_mut()
5079    }
5080    fn as_rec(&self) -> &Vec<u8> {
5081        self.prev.as_ref().unwrap().as_rec()
5082    }
5083}
5084impl<Prev: Rec> PushTupleIpAttrs<Prev> {
5085    pub fn new(prev: Prev) -> Self {
5086        Self {
5087            prev: Some(prev),
5088            header_offset: None,
5089        }
5090    }
5091    pub fn end_nested(mut self) -> Prev {
5092        let mut prev = self.prev.take().unwrap();
5093        if let Some(header_offset) = &self.header_offset {
5094            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5095        }
5096        prev
5097    }
5098    #[doc = "ipv4 source address"]
5099    pub fn push_ip_v4_src(mut self, value: std::net::Ipv4Addr) -> Self {
5100        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5101        self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
5102        self
5103    }
5104    #[doc = "ipv4 destination address"]
5105    pub fn push_ip_v4_dst(mut self, value: std::net::Ipv4Addr) -> Self {
5106        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5107        self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
5108        self
5109    }
5110    #[doc = "ipv6 source address"]
5111    pub fn push_ip_v6_src(mut self, value: std::net::Ipv6Addr) -> Self {
5112        push_header(self.as_rec_mut(), 3u16, 16 as u16);
5113        self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
5114        self
5115    }
5116    #[doc = "ipv6 destination address"]
5117    pub fn push_ip_v6_dst(mut self, value: std::net::Ipv6Addr) -> Self {
5118        push_header(self.as_rec_mut(), 4u16, 16 as u16);
5119        self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
5120        self
5121    }
5122}
5123impl<Prev: Rec> Drop for PushTupleIpAttrs<Prev> {
5124    fn drop(&mut self) {
5125        if let Some(prev) = &mut self.prev {
5126            if let Some(header_offset) = &self.header_offset {
5127                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5128            }
5129        }
5130    }
5131}
5132pub struct PushTupleAttrs<Prev: Rec> {
5133    pub(crate) prev: Option<Prev>,
5134    pub(crate) header_offset: Option<usize>,
5135}
5136impl<Prev: Rec> Rec for PushTupleAttrs<Prev> {
5137    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5138        self.prev.as_mut().unwrap().as_rec_mut()
5139    }
5140    fn as_rec(&self) -> &Vec<u8> {
5141        self.prev.as_ref().unwrap().as_rec()
5142    }
5143}
5144impl<Prev: Rec> PushTupleAttrs<Prev> {
5145    pub fn new(prev: Prev) -> Self {
5146        Self {
5147            prev: Some(prev),
5148            header_offset: None,
5149        }
5150    }
5151    pub fn end_nested(mut self) -> Prev {
5152        let mut prev = self.prev.take().unwrap();
5153        if let Some(header_offset) = &self.header_offset {
5154            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5155        }
5156        prev
5157    }
5158    #[doc = "conntrack l3 information"]
5159    pub fn nested_tuple_ip(mut self) -> PushTupleIpAttrs<Self> {
5160        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
5161        PushTupleIpAttrs {
5162            prev: Some(self),
5163            header_offset: Some(header_offset),
5164        }
5165    }
5166    #[doc = "conntrack l4 information"]
5167    pub fn nested_tuple_proto(mut self) -> PushTupleProtoAttrs<Self> {
5168        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
5169        PushTupleProtoAttrs {
5170            prev: Some(self),
5171            header_offset: Some(header_offset),
5172        }
5173    }
5174    #[doc = "conntrack zone id"]
5175    pub fn push_tuple_zone(mut self, value: u16) -> Self {
5176        push_header(self.as_rec_mut(), 3u16, 2 as u16);
5177        self.as_rec_mut().extend(value.to_be_bytes());
5178        self
5179    }
5180}
5181impl<Prev: Rec> Drop for PushTupleAttrs<Prev> {
5182    fn drop(&mut self) {
5183        if let Some(prev) = &mut self.prev {
5184            if let Some(header_offset) = &self.header_offset {
5185                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5186            }
5187        }
5188    }
5189}
5190pub struct PushProtoinfoTcpAttrs<Prev: Rec> {
5191    pub(crate) prev: Option<Prev>,
5192    pub(crate) header_offset: Option<usize>,
5193}
5194impl<Prev: Rec> Rec for PushProtoinfoTcpAttrs<Prev> {
5195    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5196        self.prev.as_mut().unwrap().as_rec_mut()
5197    }
5198    fn as_rec(&self) -> &Vec<u8> {
5199        self.prev.as_ref().unwrap().as_rec()
5200    }
5201}
5202impl<Prev: Rec> PushProtoinfoTcpAttrs<Prev> {
5203    pub fn new(prev: Prev) -> Self {
5204        Self {
5205            prev: Some(prev),
5206            header_offset: None,
5207        }
5208    }
5209    pub fn end_nested(mut self) -> Prev {
5210        let mut prev = self.prev.take().unwrap();
5211        if let Some(header_offset) = &self.header_offset {
5212            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5213        }
5214        prev
5215    }
5216    #[doc = "tcp connection state\nAssociated type: [`NfCtTcpState`] (enum)"]
5217    pub fn push_tcp_state(mut self, value: u8) -> Self {
5218        push_header(self.as_rec_mut(), 1u16, 1 as u16);
5219        self.as_rec_mut().extend(value.to_ne_bytes());
5220        self
5221    }
5222    #[doc = "window scaling factor in original direction"]
5223    pub fn push_tcp_wscale_original(mut self, value: u8) -> Self {
5224        push_header(self.as_rec_mut(), 2u16, 1 as u16);
5225        self.as_rec_mut().extend(value.to_ne_bytes());
5226        self
5227    }
5228    #[doc = "window scaling factor in reply direction"]
5229    pub fn push_tcp_wscale_reply(mut self, value: u8) -> Self {
5230        push_header(self.as_rec_mut(), 3u16, 1 as u16);
5231        self.as_rec_mut().extend(value.to_ne_bytes());
5232        self
5233    }
5234    pub fn push_tcp_flags_original(mut self, value: NfCtTcpFlagsMask) -> Self {
5235        push_header(self.as_rec_mut(), 4u16, value.as_slice().len() as u16);
5236        self.as_rec_mut().extend(value.as_slice());
5237        self
5238    }
5239    pub fn push_tcp_flags_reply(mut self, value: NfCtTcpFlagsMask) -> Self {
5240        push_header(self.as_rec_mut(), 5u16, value.as_slice().len() as u16);
5241        self.as_rec_mut().extend(value.as_slice());
5242        self
5243    }
5244}
5245impl<Prev: Rec> Drop for PushProtoinfoTcpAttrs<Prev> {
5246    fn drop(&mut self) {
5247        if let Some(prev) = &mut self.prev {
5248            if let Some(header_offset) = &self.header_offset {
5249                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5250            }
5251        }
5252    }
5253}
5254pub struct PushProtoinfoDccpAttrs<Prev: Rec> {
5255    pub(crate) prev: Option<Prev>,
5256    pub(crate) header_offset: Option<usize>,
5257}
5258impl<Prev: Rec> Rec for PushProtoinfoDccpAttrs<Prev> {
5259    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5260        self.prev.as_mut().unwrap().as_rec_mut()
5261    }
5262    fn as_rec(&self) -> &Vec<u8> {
5263        self.prev.as_ref().unwrap().as_rec()
5264    }
5265}
5266impl<Prev: Rec> PushProtoinfoDccpAttrs<Prev> {
5267    pub fn new(prev: Prev) -> Self {
5268        Self {
5269            prev: Some(prev),
5270            header_offset: None,
5271        }
5272    }
5273    pub fn end_nested(mut self) -> Prev {
5274        let mut prev = self.prev.take().unwrap();
5275        if let Some(header_offset) = &self.header_offset {
5276            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5277        }
5278        prev
5279    }
5280    #[doc = "dccp connection state"]
5281    pub fn push_dccp_state(mut self, value: u8) -> Self {
5282        push_header(self.as_rec_mut(), 1u16, 1 as u16);
5283        self.as_rec_mut().extend(value.to_ne_bytes());
5284        self
5285    }
5286    pub fn push_dccp_role(mut self, value: u8) -> Self {
5287        push_header(self.as_rec_mut(), 2u16, 1 as u16);
5288        self.as_rec_mut().extend(value.to_ne_bytes());
5289        self
5290    }
5291    pub fn push_dccp_handshake_seq(mut self, value: u64) -> Self {
5292        push_header(self.as_rec_mut(), 3u16, 8 as u16);
5293        self.as_rec_mut().extend(value.to_be_bytes());
5294        self
5295    }
5296    pub fn push_dccp_pad(mut self, value: &[u8]) -> Self {
5297        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
5298        self.as_rec_mut().extend(value);
5299        self
5300    }
5301}
5302impl<Prev: Rec> Drop for PushProtoinfoDccpAttrs<Prev> {
5303    fn drop(&mut self) {
5304        if let Some(prev) = &mut self.prev {
5305            if let Some(header_offset) = &self.header_offset {
5306                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5307            }
5308        }
5309    }
5310}
5311pub struct PushProtoinfoSctpAttrs<Prev: Rec> {
5312    pub(crate) prev: Option<Prev>,
5313    pub(crate) header_offset: Option<usize>,
5314}
5315impl<Prev: Rec> Rec for PushProtoinfoSctpAttrs<Prev> {
5316    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5317        self.prev.as_mut().unwrap().as_rec_mut()
5318    }
5319    fn as_rec(&self) -> &Vec<u8> {
5320        self.prev.as_ref().unwrap().as_rec()
5321    }
5322}
5323impl<Prev: Rec> PushProtoinfoSctpAttrs<Prev> {
5324    pub fn new(prev: Prev) -> Self {
5325        Self {
5326            prev: Some(prev),
5327            header_offset: None,
5328        }
5329    }
5330    pub fn end_nested(mut self) -> Prev {
5331        let mut prev = self.prev.take().unwrap();
5332        if let Some(header_offset) = &self.header_offset {
5333            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5334        }
5335        prev
5336    }
5337    #[doc = "sctp connection state\nAssociated type: [`NfCtSctpState`] (enum)"]
5338    pub fn push_sctp_state(mut self, value: u8) -> Self {
5339        push_header(self.as_rec_mut(), 1u16, 1 as u16);
5340        self.as_rec_mut().extend(value.to_ne_bytes());
5341        self
5342    }
5343    pub fn push_vtag_original(mut self, value: u32) -> Self {
5344        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5345        self.as_rec_mut().extend(value.to_be_bytes());
5346        self
5347    }
5348    pub fn push_vtag_reply(mut self, value: u32) -> Self {
5349        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5350        self.as_rec_mut().extend(value.to_be_bytes());
5351        self
5352    }
5353}
5354impl<Prev: Rec> Drop for PushProtoinfoSctpAttrs<Prev> {
5355    fn drop(&mut self) {
5356        if let Some(prev) = &mut self.prev {
5357            if let Some(header_offset) = &self.header_offset {
5358                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5359            }
5360        }
5361    }
5362}
5363pub struct PushProtoinfoAttrs<Prev: Rec> {
5364    pub(crate) prev: Option<Prev>,
5365    pub(crate) header_offset: Option<usize>,
5366}
5367impl<Prev: Rec> Rec for PushProtoinfoAttrs<Prev> {
5368    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5369        self.prev.as_mut().unwrap().as_rec_mut()
5370    }
5371    fn as_rec(&self) -> &Vec<u8> {
5372        self.prev.as_ref().unwrap().as_rec()
5373    }
5374}
5375impl<Prev: Rec> PushProtoinfoAttrs<Prev> {
5376    pub fn new(prev: Prev) -> Self {
5377        Self {
5378            prev: Some(prev),
5379            header_offset: None,
5380        }
5381    }
5382    pub fn end_nested(mut self) -> Prev {
5383        let mut prev = self.prev.take().unwrap();
5384        if let Some(header_offset) = &self.header_offset {
5385            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5386        }
5387        prev
5388    }
5389    #[doc = "conntrack tcp state information"]
5390    pub fn nested_protoinfo_tcp(mut self) -> PushProtoinfoTcpAttrs<Self> {
5391        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
5392        PushProtoinfoTcpAttrs {
5393            prev: Some(self),
5394            header_offset: Some(header_offset),
5395        }
5396    }
5397    #[doc = "conntrack dccp state information"]
5398    pub fn nested_protoinfo_dccp(mut self) -> PushProtoinfoDccpAttrs<Self> {
5399        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
5400        PushProtoinfoDccpAttrs {
5401            prev: Some(self),
5402            header_offset: Some(header_offset),
5403        }
5404    }
5405    #[doc = "conntrack sctp state information"]
5406    pub fn nested_protoinfo_sctp(mut self) -> PushProtoinfoSctpAttrs<Self> {
5407        let header_offset = push_nested_header(self.as_rec_mut(), 3u16);
5408        PushProtoinfoSctpAttrs {
5409            prev: Some(self),
5410            header_offset: Some(header_offset),
5411        }
5412    }
5413}
5414impl<Prev: Rec> Drop for PushProtoinfoAttrs<Prev> {
5415    fn drop(&mut self) {
5416        if let Some(prev) = &mut self.prev {
5417            if let Some(header_offset) = &self.header_offset {
5418                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5419            }
5420        }
5421    }
5422}
5423pub struct PushHelpAttrs<Prev: Rec> {
5424    pub(crate) prev: Option<Prev>,
5425    pub(crate) header_offset: Option<usize>,
5426}
5427impl<Prev: Rec> Rec for PushHelpAttrs<Prev> {
5428    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5429        self.prev.as_mut().unwrap().as_rec_mut()
5430    }
5431    fn as_rec(&self) -> &Vec<u8> {
5432        self.prev.as_ref().unwrap().as_rec()
5433    }
5434}
5435impl<Prev: Rec> PushHelpAttrs<Prev> {
5436    pub fn new(prev: Prev) -> Self {
5437        Self {
5438            prev: Some(prev),
5439            header_offset: None,
5440        }
5441    }
5442    pub fn end_nested(mut self) -> Prev {
5443        let mut prev = self.prev.take().unwrap();
5444        if let Some(header_offset) = &self.header_offset {
5445            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5446        }
5447        prev
5448    }
5449    #[doc = "helper name"]
5450    pub fn push_help_name(mut self, value: &CStr) -> Self {
5451        push_header(
5452            self.as_rec_mut(),
5453            1u16,
5454            value.to_bytes_with_nul().len() as u16,
5455        );
5456        self.as_rec_mut().extend(value.to_bytes_with_nul());
5457        self
5458    }
5459    #[doc = "helper name"]
5460    pub fn push_help_name_bytes(mut self, value: &[u8]) -> Self {
5461        push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
5462        self.as_rec_mut().extend(value);
5463        self.as_rec_mut().push(0);
5464        self
5465    }
5466}
5467impl<Prev: Rec> Drop for PushHelpAttrs<Prev> {
5468    fn drop(&mut self) {
5469        if let Some(prev) = &mut self.prev {
5470            if let Some(header_offset) = &self.header_offset {
5471                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5472            }
5473        }
5474    }
5475}
5476pub struct PushNatProtoAttrs<Prev: Rec> {
5477    pub(crate) prev: Option<Prev>,
5478    pub(crate) header_offset: Option<usize>,
5479}
5480impl<Prev: Rec> Rec for PushNatProtoAttrs<Prev> {
5481    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5482        self.prev.as_mut().unwrap().as_rec_mut()
5483    }
5484    fn as_rec(&self) -> &Vec<u8> {
5485        self.prev.as_ref().unwrap().as_rec()
5486    }
5487}
5488impl<Prev: Rec> PushNatProtoAttrs<Prev> {
5489    pub fn new(prev: Prev) -> Self {
5490        Self {
5491            prev: Some(prev),
5492            header_offset: None,
5493        }
5494    }
5495    pub fn end_nested(mut self) -> Prev {
5496        let mut prev = self.prev.take().unwrap();
5497        if let Some(header_offset) = &self.header_offset {
5498            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5499        }
5500        prev
5501    }
5502    pub fn push_nat_port_min(mut self, value: u16) -> Self {
5503        push_header(self.as_rec_mut(), 1u16, 2 as u16);
5504        self.as_rec_mut().extend(value.to_be_bytes());
5505        self
5506    }
5507    pub fn push_nat_port_max(mut self, value: u16) -> Self {
5508        push_header(self.as_rec_mut(), 2u16, 2 as u16);
5509        self.as_rec_mut().extend(value.to_be_bytes());
5510        self
5511    }
5512}
5513impl<Prev: Rec> Drop for PushNatProtoAttrs<Prev> {
5514    fn drop(&mut self) {
5515        if let Some(prev) = &mut self.prev {
5516            if let Some(header_offset) = &self.header_offset {
5517                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5518            }
5519        }
5520    }
5521}
5522pub struct PushNatAttrs<Prev: Rec> {
5523    pub(crate) prev: Option<Prev>,
5524    pub(crate) header_offset: Option<usize>,
5525}
5526impl<Prev: Rec> Rec for PushNatAttrs<Prev> {
5527    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5528        self.prev.as_mut().unwrap().as_rec_mut()
5529    }
5530    fn as_rec(&self) -> &Vec<u8> {
5531        self.prev.as_ref().unwrap().as_rec()
5532    }
5533}
5534impl<Prev: Rec> PushNatAttrs<Prev> {
5535    pub fn new(prev: Prev) -> Self {
5536        Self {
5537            prev: Some(prev),
5538            header_offset: None,
5539        }
5540    }
5541    pub fn end_nested(mut self) -> Prev {
5542        let mut prev = self.prev.take().unwrap();
5543        if let Some(header_offset) = &self.header_offset {
5544            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5545        }
5546        prev
5547    }
5548    pub fn push_nat_v4_minip(mut self, value: u32) -> Self {
5549        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5550        self.as_rec_mut().extend(value.to_be_bytes());
5551        self
5552    }
5553    pub fn push_nat_v4_maxip(mut self, value: u32) -> Self {
5554        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5555        self.as_rec_mut().extend(value.to_be_bytes());
5556        self
5557    }
5558    pub fn push_nat_v6_minip(mut self, value: &[u8]) -> Self {
5559        push_header(self.as_rec_mut(), 3u16, value.len() as u16);
5560        self.as_rec_mut().extend(value);
5561        self
5562    }
5563    pub fn push_nat_v6_maxip(mut self, value: &[u8]) -> Self {
5564        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
5565        self.as_rec_mut().extend(value);
5566        self
5567    }
5568    pub fn nested_nat_proto(mut self) -> PushNatProtoAttrs<Self> {
5569        let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
5570        PushNatProtoAttrs {
5571            prev: Some(self),
5572            header_offset: Some(header_offset),
5573        }
5574    }
5575}
5576impl<Prev: Rec> Drop for PushNatAttrs<Prev> {
5577    fn drop(&mut self) {
5578        if let Some(prev) = &mut self.prev {
5579            if let Some(header_offset) = &self.header_offset {
5580                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5581            }
5582        }
5583    }
5584}
5585pub struct PushSeqadjAttrs<Prev: Rec> {
5586    pub(crate) prev: Option<Prev>,
5587    pub(crate) header_offset: Option<usize>,
5588}
5589impl<Prev: Rec> Rec for PushSeqadjAttrs<Prev> {
5590    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5591        self.prev.as_mut().unwrap().as_rec_mut()
5592    }
5593    fn as_rec(&self) -> &Vec<u8> {
5594        self.prev.as_ref().unwrap().as_rec()
5595    }
5596}
5597impl<Prev: Rec> PushSeqadjAttrs<Prev> {
5598    pub fn new(prev: Prev) -> Self {
5599        Self {
5600            prev: Some(prev),
5601            header_offset: None,
5602        }
5603    }
5604    pub fn end_nested(mut self) -> Prev {
5605        let mut prev = self.prev.take().unwrap();
5606        if let Some(header_offset) = &self.header_offset {
5607            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5608        }
5609        prev
5610    }
5611    pub fn push_correction_pos(mut self, value: u32) -> Self {
5612        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5613        self.as_rec_mut().extend(value.to_be_bytes());
5614        self
5615    }
5616    pub fn push_offset_before(mut self, value: u32) -> Self {
5617        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5618        self.as_rec_mut().extend(value.to_be_bytes());
5619        self
5620    }
5621    pub fn push_offset_after(mut self, value: u32) -> Self {
5622        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5623        self.as_rec_mut().extend(value.to_be_bytes());
5624        self
5625    }
5626}
5627impl<Prev: Rec> Drop for PushSeqadjAttrs<Prev> {
5628    fn drop(&mut self) {
5629        if let Some(prev) = &mut self.prev {
5630            if let Some(header_offset) = &self.header_offset {
5631                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5632            }
5633        }
5634    }
5635}
5636pub struct PushSecctxAttrs<Prev: Rec> {
5637    pub(crate) prev: Option<Prev>,
5638    pub(crate) header_offset: Option<usize>,
5639}
5640impl<Prev: Rec> Rec for PushSecctxAttrs<Prev> {
5641    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5642        self.prev.as_mut().unwrap().as_rec_mut()
5643    }
5644    fn as_rec(&self) -> &Vec<u8> {
5645        self.prev.as_ref().unwrap().as_rec()
5646    }
5647}
5648impl<Prev: Rec> PushSecctxAttrs<Prev> {
5649    pub fn new(prev: Prev) -> Self {
5650        Self {
5651            prev: Some(prev),
5652            header_offset: None,
5653        }
5654    }
5655    pub fn end_nested(mut self) -> Prev {
5656        let mut prev = self.prev.take().unwrap();
5657        if let Some(header_offset) = &self.header_offset {
5658            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5659        }
5660        prev
5661    }
5662    pub fn push_secctx_name(mut self, value: &CStr) -> Self {
5663        push_header(
5664            self.as_rec_mut(),
5665            1u16,
5666            value.to_bytes_with_nul().len() as u16,
5667        );
5668        self.as_rec_mut().extend(value.to_bytes_with_nul());
5669        self
5670    }
5671    pub fn push_secctx_name_bytes(mut self, value: &[u8]) -> Self {
5672        push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
5673        self.as_rec_mut().extend(value);
5674        self.as_rec_mut().push(0);
5675        self
5676    }
5677}
5678impl<Prev: Rec> Drop for PushSecctxAttrs<Prev> {
5679    fn drop(&mut self) {
5680        if let Some(prev) = &mut self.prev {
5681            if let Some(header_offset) = &self.header_offset {
5682                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5683            }
5684        }
5685    }
5686}
5687pub struct PushSynproxyAttrs<Prev: Rec> {
5688    pub(crate) prev: Option<Prev>,
5689    pub(crate) header_offset: Option<usize>,
5690}
5691impl<Prev: Rec> Rec for PushSynproxyAttrs<Prev> {
5692    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5693        self.prev.as_mut().unwrap().as_rec_mut()
5694    }
5695    fn as_rec(&self) -> &Vec<u8> {
5696        self.prev.as_ref().unwrap().as_rec()
5697    }
5698}
5699impl<Prev: Rec> PushSynproxyAttrs<Prev> {
5700    pub fn new(prev: Prev) -> Self {
5701        Self {
5702            prev: Some(prev),
5703            header_offset: None,
5704        }
5705    }
5706    pub fn end_nested(mut self) -> Prev {
5707        let mut prev = self.prev.take().unwrap();
5708        if let Some(header_offset) = &self.header_offset {
5709            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5710        }
5711        prev
5712    }
5713    pub fn push_isn(mut self, value: u32) -> Self {
5714        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5715        self.as_rec_mut().extend(value.to_be_bytes());
5716        self
5717    }
5718    pub fn push_its(mut self, value: u32) -> Self {
5719        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5720        self.as_rec_mut().extend(value.to_be_bytes());
5721        self
5722    }
5723    pub fn push_tsoff(mut self, value: u32) -> Self {
5724        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5725        self.as_rec_mut().extend(value.to_be_bytes());
5726        self
5727    }
5728}
5729impl<Prev: Rec> Drop for PushSynproxyAttrs<Prev> {
5730    fn drop(&mut self) {
5731        if let Some(prev) = &mut self.prev {
5732            if let Some(header_offset) = &self.header_offset {
5733                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5734            }
5735        }
5736    }
5737}
5738pub struct PushConntrackAttrs<Prev: Rec> {
5739    pub(crate) prev: Option<Prev>,
5740    pub(crate) header_offset: Option<usize>,
5741}
5742impl<Prev: Rec> Rec for PushConntrackAttrs<Prev> {
5743    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5744        self.prev.as_mut().unwrap().as_rec_mut()
5745    }
5746    fn as_rec(&self) -> &Vec<u8> {
5747        self.prev.as_ref().unwrap().as_rec()
5748    }
5749}
5750impl<Prev: Rec> PushConntrackAttrs<Prev> {
5751    pub fn new(prev: Prev) -> Self {
5752        Self {
5753            prev: Some(prev),
5754            header_offset: None,
5755        }
5756    }
5757    pub fn end_nested(mut self) -> Prev {
5758        let mut prev = self.prev.take().unwrap();
5759        if let Some(header_offset) = &self.header_offset {
5760            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5761        }
5762        prev
5763    }
5764    #[doc = "conntrack l3\\+l4 protocol information, original direction"]
5765    pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
5766        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
5767        PushTupleAttrs {
5768            prev: Some(self),
5769            header_offset: Some(header_offset),
5770        }
5771    }
5772    #[doc = "conntrack l3\\+l4 protocol information, reply direction"]
5773    pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
5774        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
5775        PushTupleAttrs {
5776            prev: Some(self),
5777            header_offset: Some(header_offset),
5778        }
5779    }
5780    #[doc = "conntrack flag bits\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
5781    pub fn push_status(mut self, value: u32) -> Self {
5782        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5783        self.as_rec_mut().extend(value.to_be_bytes());
5784        self
5785    }
5786    pub fn nested_protoinfo(mut self) -> PushProtoinfoAttrs<Self> {
5787        let header_offset = push_nested_header(self.as_rec_mut(), 4u16);
5788        PushProtoinfoAttrs {
5789            prev: Some(self),
5790            header_offset: Some(header_offset),
5791        }
5792    }
5793    pub fn nested_help(mut self) -> PushHelpAttrs<Self> {
5794        let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
5795        PushHelpAttrs {
5796            prev: Some(self),
5797            header_offset: Some(header_offset),
5798        }
5799    }
5800    pub fn nested_nat_src(mut self) -> PushNatAttrs<Self> {
5801        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
5802        PushNatAttrs {
5803            prev: Some(self),
5804            header_offset: Some(header_offset),
5805        }
5806    }
5807    pub fn push_timeout(mut self, value: u32) -> Self {
5808        push_header(self.as_rec_mut(), 7u16, 4 as u16);
5809        self.as_rec_mut().extend(value.to_be_bytes());
5810        self
5811    }
5812    pub fn push_mark(mut self, value: u32) -> Self {
5813        push_header(self.as_rec_mut(), 8u16, 4 as u16);
5814        self.as_rec_mut().extend(value.to_be_bytes());
5815        self
5816    }
5817    pub fn nested_counters_orig(mut self) -> PushCounterAttrs<Self> {
5818        let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
5819        PushCounterAttrs {
5820            prev: Some(self),
5821            header_offset: Some(header_offset),
5822        }
5823    }
5824    pub fn nested_counters_reply(mut self) -> PushCounterAttrs<Self> {
5825        let header_offset = push_nested_header(self.as_rec_mut(), 10u16);
5826        PushCounterAttrs {
5827            prev: Some(self),
5828            header_offset: Some(header_offset),
5829        }
5830    }
5831    pub fn push_use(mut self, value: u32) -> Self {
5832        push_header(self.as_rec_mut(), 11u16, 4 as u16);
5833        self.as_rec_mut().extend(value.to_be_bytes());
5834        self
5835    }
5836    pub fn push_id(mut self, value: u32) -> Self {
5837        push_header(self.as_rec_mut(), 12u16, 4 as u16);
5838        self.as_rec_mut().extend(value.to_be_bytes());
5839        self
5840    }
5841    pub fn nested_nat_dst(mut self) -> PushNatAttrs<Self> {
5842        let header_offset = push_nested_header(self.as_rec_mut(), 13u16);
5843        PushNatAttrs {
5844            prev: Some(self),
5845            header_offset: Some(header_offset),
5846        }
5847    }
5848    pub fn nested_tuple_master(mut self) -> PushTupleAttrs<Self> {
5849        let header_offset = push_nested_header(self.as_rec_mut(), 14u16);
5850        PushTupleAttrs {
5851            prev: Some(self),
5852            header_offset: Some(header_offset),
5853        }
5854    }
5855    pub fn nested_seq_adj_orig(mut self) -> PushSeqadjAttrs<Self> {
5856        let header_offset = push_nested_header(self.as_rec_mut(), 15u16);
5857        PushSeqadjAttrs {
5858            prev: Some(self),
5859            header_offset: Some(header_offset),
5860        }
5861    }
5862    pub fn nested_seq_adj_reply(mut self) -> PushSeqadjAttrs<Self> {
5863        let header_offset = push_nested_header(self.as_rec_mut(), 16u16);
5864        PushSeqadjAttrs {
5865            prev: Some(self),
5866            header_offset: Some(header_offset),
5867        }
5868    }
5869    #[doc = "obsolete"]
5870    pub fn push_secmark(mut self, value: &[u8]) -> Self {
5871        push_header(self.as_rec_mut(), 17u16, value.len() as u16);
5872        self.as_rec_mut().extend(value);
5873        self
5874    }
5875    #[doc = "conntrack zone id"]
5876    pub fn push_zone(mut self, value: u16) -> Self {
5877        push_header(self.as_rec_mut(), 18u16, 2 as u16);
5878        self.as_rec_mut().extend(value.to_be_bytes());
5879        self
5880    }
5881    pub fn nested_secctx(mut self) -> PushSecctxAttrs<Self> {
5882        let header_offset = push_nested_header(self.as_rec_mut(), 19u16);
5883        PushSecctxAttrs {
5884            prev: Some(self),
5885            header_offset: Some(header_offset),
5886        }
5887    }
5888    pub fn push_timestamp(mut self, value: u64) -> Self {
5889        push_header(self.as_rec_mut(), 20u16, 8 as u16);
5890        self.as_rec_mut().extend(value.to_be_bytes());
5891        self
5892    }
5893    pub fn push_mark_mask(mut self, value: u32) -> Self {
5894        push_header(self.as_rec_mut(), 21u16, 4 as u16);
5895        self.as_rec_mut().extend(value.to_be_bytes());
5896        self
5897    }
5898    pub fn push_labels(mut self, value: &[u8]) -> Self {
5899        push_header(self.as_rec_mut(), 22u16, value.len() as u16);
5900        self.as_rec_mut().extend(value);
5901        self
5902    }
5903    pub fn push_labels_mask(mut self, value: &[u8]) -> Self {
5904        push_header(self.as_rec_mut(), 23u16, value.len() as u16);
5905        self.as_rec_mut().extend(value);
5906        self
5907    }
5908    pub fn nested_synproxy(mut self) -> PushSynproxyAttrs<Self> {
5909        let header_offset = push_nested_header(self.as_rec_mut(), 24u16);
5910        PushSynproxyAttrs {
5911            prev: Some(self),
5912            header_offset: Some(header_offset),
5913        }
5914    }
5915    pub fn nested_filter(mut self) -> PushTupleAttrs<Self> {
5916        let header_offset = push_nested_header(self.as_rec_mut(), 25u16);
5917        PushTupleAttrs {
5918            prev: Some(self),
5919            header_offset: Some(header_offset),
5920        }
5921    }
5922    #[doc = "conntrack flag bits to change\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
5923    pub fn push_status_mask(mut self, value: u32) -> Self {
5924        push_header(self.as_rec_mut(), 26u16, 4 as u16);
5925        self.as_rec_mut().extend(value.to_be_bytes());
5926        self
5927    }
5928    pub fn push_timestamp_event(mut self, value: u64) -> Self {
5929        push_header(self.as_rec_mut(), 27u16, 8 as u16);
5930        self.as_rec_mut().extend(value.to_be_bytes());
5931        self
5932    }
5933}
5934impl<Prev: Rec> Drop for PushConntrackAttrs<Prev> {
5935    fn drop(&mut self) {
5936        if let Some(prev) = &mut self.prev {
5937            if let Some(header_offset) = &self.header_offset {
5938                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5939            }
5940        }
5941    }
5942}
5943pub struct PushConntrackStatsAttrs<Prev: Rec> {
5944    pub(crate) prev: Option<Prev>,
5945    pub(crate) header_offset: Option<usize>,
5946}
5947impl<Prev: Rec> Rec for PushConntrackStatsAttrs<Prev> {
5948    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5949        self.prev.as_mut().unwrap().as_rec_mut()
5950    }
5951    fn as_rec(&self) -> &Vec<u8> {
5952        self.prev.as_ref().unwrap().as_rec()
5953    }
5954}
5955impl<Prev: Rec> PushConntrackStatsAttrs<Prev> {
5956    pub fn new(prev: Prev) -> Self {
5957        Self {
5958            prev: Some(prev),
5959            header_offset: None,
5960        }
5961    }
5962    pub fn end_nested(mut self) -> Prev {
5963        let mut prev = self.prev.take().unwrap();
5964        if let Some(header_offset) = &self.header_offset {
5965            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5966        }
5967        prev
5968    }
5969    #[doc = "obsolete"]
5970    pub fn push_searched(mut self, value: u32) -> Self {
5971        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5972        self.as_rec_mut().extend(value.to_be_bytes());
5973        self
5974    }
5975    pub fn push_found(mut self, value: u32) -> Self {
5976        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5977        self.as_rec_mut().extend(value.to_be_bytes());
5978        self
5979    }
5980    #[doc = "obsolete"]
5981    pub fn push_new(mut self, value: u32) -> Self {
5982        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5983        self.as_rec_mut().extend(value.to_be_bytes());
5984        self
5985    }
5986    #[doc = "obsolete"]
5987    pub fn push_invalid(mut self, value: u32) -> Self {
5988        push_header(self.as_rec_mut(), 4u16, 4 as u16);
5989        self.as_rec_mut().extend(value.to_be_bytes());
5990        self
5991    }
5992    #[doc = "obsolete"]
5993    pub fn push_ignore(mut self, value: u32) -> Self {
5994        push_header(self.as_rec_mut(), 5u16, 4 as u16);
5995        self.as_rec_mut().extend(value.to_be_bytes());
5996        self
5997    }
5998    #[doc = "obsolete"]
5999    pub fn push_delete(mut self, value: u32) -> Self {
6000        push_header(self.as_rec_mut(), 6u16, 4 as u16);
6001        self.as_rec_mut().extend(value.to_be_bytes());
6002        self
6003    }
6004    #[doc = "obsolete"]
6005    pub fn push_delete_list(mut self, value: u32) -> Self {
6006        push_header(self.as_rec_mut(), 7u16, 4 as u16);
6007        self.as_rec_mut().extend(value.to_be_bytes());
6008        self
6009    }
6010    pub fn push_insert(mut self, value: u32) -> Self {
6011        push_header(self.as_rec_mut(), 8u16, 4 as u16);
6012        self.as_rec_mut().extend(value.to_be_bytes());
6013        self
6014    }
6015    pub fn push_insert_failed(mut self, value: u32) -> Self {
6016        push_header(self.as_rec_mut(), 9u16, 4 as u16);
6017        self.as_rec_mut().extend(value.to_be_bytes());
6018        self
6019    }
6020    pub fn push_drop(mut self, value: u32) -> Self {
6021        push_header(self.as_rec_mut(), 10u16, 4 as u16);
6022        self.as_rec_mut().extend(value.to_be_bytes());
6023        self
6024    }
6025    pub fn push_early_drop(mut self, value: u32) -> Self {
6026        push_header(self.as_rec_mut(), 11u16, 4 as u16);
6027        self.as_rec_mut().extend(value.to_be_bytes());
6028        self
6029    }
6030    pub fn push_error(mut self, value: u32) -> Self {
6031        push_header(self.as_rec_mut(), 12u16, 4 as u16);
6032        self.as_rec_mut().extend(value.to_be_bytes());
6033        self
6034    }
6035    pub fn push_search_restart(mut self, value: u32) -> Self {
6036        push_header(self.as_rec_mut(), 13u16, 4 as u16);
6037        self.as_rec_mut().extend(value.to_be_bytes());
6038        self
6039    }
6040    pub fn push_clash_resolve(mut self, value: u32) -> Self {
6041        push_header(self.as_rec_mut(), 14u16, 4 as u16);
6042        self.as_rec_mut().extend(value.to_be_bytes());
6043        self
6044    }
6045    pub fn push_chain_toolong(mut self, value: u32) -> Self {
6046        push_header(self.as_rec_mut(), 15u16, 4 as u16);
6047        self.as_rec_mut().extend(value.to_be_bytes());
6048        self
6049    }
6050}
6051impl<Prev: Rec> Drop for PushConntrackStatsAttrs<Prev> {
6052    fn drop(&mut self) {
6053        if let Some(prev) = &mut self.prev {
6054            if let Some(header_offset) = &self.header_offset {
6055                finalize_nested_header(prev.as_rec_mut(), *header_offset);
6056            }
6057        }
6058    }
6059}
6060#[doc = "get / dump entries\nRequest attributes:\n- [.push_status()](PushConntrackAttrs::push_status)\n- [.push_mark()](PushConntrackAttrs::push_mark)\n- [.push_zone()](PushConntrackAttrs::push_zone)\n- [.nested_filter()](PushConntrackAttrs::nested_filter)\n\nReply attributes:\n- [.get_tuple_orig()](IterableConntrackAttrs::get_tuple_orig)\n- [.get_tuple_reply()](IterableConntrackAttrs::get_tuple_reply)\n- [.get_status()](IterableConntrackAttrs::get_status)\n- [.get_protoinfo()](IterableConntrackAttrs::get_protoinfo)\n- [.get_help()](IterableConntrackAttrs::get_help)\n- [.get_nat_src()](IterableConntrackAttrs::get_nat_src)\n- [.get_timeout()](IterableConntrackAttrs::get_timeout)\n- [.get_mark()](IterableConntrackAttrs::get_mark)\n- [.get_counters_orig()](IterableConntrackAttrs::get_counters_orig)\n- [.get_counters_reply()](IterableConntrackAttrs::get_counters_reply)\n- [.get_use()](IterableConntrackAttrs::get_use)\n- [.get_id()](IterableConntrackAttrs::get_id)\n- [.get_nat_dst()](IterableConntrackAttrs::get_nat_dst)\n- [.get_tuple_master()](IterableConntrackAttrs::get_tuple_master)\n- [.get_seq_adj_orig()](IterableConntrackAttrs::get_seq_adj_orig)\n- [.get_seq_adj_reply()](IterableConntrackAttrs::get_seq_adj_reply)\n- [.get_zone()](IterableConntrackAttrs::get_zone)\n- [.get_secctx()](IterableConntrackAttrs::get_secctx)\n- [.get_labels()](IterableConntrackAttrs::get_labels)\n- [.get_synproxy()](IterableConntrackAttrs::get_synproxy)\n"]
6061#[derive(Debug)]
6062pub struct OpGetDump<'r> {
6063    request: Request<'r>,
6064}
6065impl<'r> OpGetDump<'r> {
6066    pub fn new(mut request: Request<'r>, header: &Nfgenmsg) -> Self {
6067        Self::write_header(request.buf_mut(), header);
6068        Self {
6069            request: request.set_dump(),
6070        }
6071    }
6072    pub fn encode_request<'buf>(
6073        buf: &'buf mut Vec<u8>,
6074        header: &Nfgenmsg,
6075    ) -> PushConntrackAttrs<&'buf mut Vec<u8>> {
6076        Self::write_header(buf, header);
6077        PushConntrackAttrs::new(buf)
6078    }
6079    pub fn encode(&mut self) -> PushConntrackAttrs<&mut Vec<u8>> {
6080        PushConntrackAttrs::new(self.request.buf_mut())
6081    }
6082    pub fn into_encoder(self) -> PushConntrackAttrs<RequestBuf<'r>> {
6083        PushConntrackAttrs::new(self.request.buf)
6084    }
6085    pub fn decode_request<'a>(buf: &'a [u8]) -> (Nfgenmsg, IterableConntrackAttrs<'a>) {
6086        let (header, attrs) = buf.split_at(buf.len().min(Nfgenmsg::len()));
6087        (
6088            Nfgenmsg::new_from_slice(header).unwrap_or_default(),
6089            IterableConntrackAttrs::with_loc(attrs, buf.as_ptr() as usize),
6090        )
6091    }
6092    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Nfgenmsg) {
6093        prev.as_rec_mut().extend(header.as_slice());
6094    }
6095}
6096impl NetlinkRequest for OpGetDump<'_> {
6097    fn protocol(&self) -> Protocol {
6098        Protocol::Raw {
6099            protonum: 12u16,
6100            request_type: 257u16,
6101        }
6102    }
6103    fn flags(&self) -> u16 {
6104        self.request.flags
6105    }
6106    fn payload(&self) -> &[u8] {
6107        self.request.buf()
6108    }
6109    type ReplyType<'buf> = (Nfgenmsg, IterableConntrackAttrs<'buf>);
6110    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6111        Self::decode_request(buf)
6112    }
6113    fn lookup(
6114        buf: &[u8],
6115        offset: usize,
6116        missing_type: Option<u16>,
6117    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6118        Self::decode_request(buf)
6119            .1
6120            .lookup_attr(offset, missing_type)
6121    }
6122}
6123#[doc = "get / dump entries\nRequest attributes:\n- [.nested_tuple_orig()](PushConntrackAttrs::nested_tuple_orig)\n- [.nested_tuple_reply()](PushConntrackAttrs::nested_tuple_reply)\n- [.push_zone()](PushConntrackAttrs::push_zone)\n\nReply attributes:\n- [.get_tuple_orig()](IterableConntrackAttrs::get_tuple_orig)\n- [.get_tuple_reply()](IterableConntrackAttrs::get_tuple_reply)\n- [.get_status()](IterableConntrackAttrs::get_status)\n- [.get_protoinfo()](IterableConntrackAttrs::get_protoinfo)\n- [.get_help()](IterableConntrackAttrs::get_help)\n- [.get_nat_src()](IterableConntrackAttrs::get_nat_src)\n- [.get_timeout()](IterableConntrackAttrs::get_timeout)\n- [.get_mark()](IterableConntrackAttrs::get_mark)\n- [.get_counters_orig()](IterableConntrackAttrs::get_counters_orig)\n- [.get_counters_reply()](IterableConntrackAttrs::get_counters_reply)\n- [.get_use()](IterableConntrackAttrs::get_use)\n- [.get_id()](IterableConntrackAttrs::get_id)\n- [.get_nat_dst()](IterableConntrackAttrs::get_nat_dst)\n- [.get_tuple_master()](IterableConntrackAttrs::get_tuple_master)\n- [.get_seq_adj_orig()](IterableConntrackAttrs::get_seq_adj_orig)\n- [.get_seq_adj_reply()](IterableConntrackAttrs::get_seq_adj_reply)\n- [.get_zone()](IterableConntrackAttrs::get_zone)\n- [.get_secctx()](IterableConntrackAttrs::get_secctx)\n- [.get_labels()](IterableConntrackAttrs::get_labels)\n- [.get_synproxy()](IterableConntrackAttrs::get_synproxy)\n"]
6124#[derive(Debug)]
6125pub struct OpGetDo<'r> {
6126    request: Request<'r>,
6127}
6128impl<'r> OpGetDo<'r> {
6129    pub fn new(mut request: Request<'r>, header: &Nfgenmsg) -> Self {
6130        Self::write_header(request.buf_mut(), header);
6131        Self { request: request }
6132    }
6133    pub fn encode_request<'buf>(
6134        buf: &'buf mut Vec<u8>,
6135        header: &Nfgenmsg,
6136    ) -> PushConntrackAttrs<&'buf mut Vec<u8>> {
6137        Self::write_header(buf, header);
6138        PushConntrackAttrs::new(buf)
6139    }
6140    pub fn encode(&mut self) -> PushConntrackAttrs<&mut Vec<u8>> {
6141        PushConntrackAttrs::new(self.request.buf_mut())
6142    }
6143    pub fn into_encoder(self) -> PushConntrackAttrs<RequestBuf<'r>> {
6144        PushConntrackAttrs::new(self.request.buf)
6145    }
6146    pub fn decode_request<'a>(buf: &'a [u8]) -> (Nfgenmsg, IterableConntrackAttrs<'a>) {
6147        let (header, attrs) = buf.split_at(buf.len().min(Nfgenmsg::len()));
6148        (
6149            Nfgenmsg::new_from_slice(header).unwrap_or_default(),
6150            IterableConntrackAttrs::with_loc(attrs, buf.as_ptr() as usize),
6151        )
6152    }
6153    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Nfgenmsg) {
6154        prev.as_rec_mut().extend(header.as_slice());
6155    }
6156}
6157impl NetlinkRequest for OpGetDo<'_> {
6158    fn protocol(&self) -> Protocol {
6159        Protocol::Raw {
6160            protonum: 12u16,
6161            request_type: 257u16,
6162        }
6163    }
6164    fn flags(&self) -> u16 {
6165        self.request.flags
6166    }
6167    fn payload(&self) -> &[u8] {
6168        self.request.buf()
6169    }
6170    type ReplyType<'buf> = (Nfgenmsg, IterableConntrackAttrs<'buf>);
6171    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6172        Self::decode_request(buf)
6173    }
6174    fn lookup(
6175        buf: &[u8],
6176        offset: usize,
6177        missing_type: Option<u16>,
6178    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6179        Self::decode_request(buf)
6180            .1
6181            .lookup_attr(offset, missing_type)
6182    }
6183}
6184#[doc = "dump pcpu conntrack stats\n\nReply attributes:\n- [.get_searched()](IterableConntrackStatsAttrs::get_searched)\n- [.get_found()](IterableConntrackStatsAttrs::get_found)\n- [.get_insert()](IterableConntrackStatsAttrs::get_insert)\n- [.get_insert_failed()](IterableConntrackStatsAttrs::get_insert_failed)\n- [.get_drop()](IterableConntrackStatsAttrs::get_drop)\n- [.get_early_drop()](IterableConntrackStatsAttrs::get_early_drop)\n- [.get_error()](IterableConntrackStatsAttrs::get_error)\n- [.get_search_restart()](IterableConntrackStatsAttrs::get_search_restart)\n- [.get_clash_resolve()](IterableConntrackStatsAttrs::get_clash_resolve)\n- [.get_chain_toolong()](IterableConntrackStatsAttrs::get_chain_toolong)\n"]
6185#[derive(Debug)]
6186pub struct OpGetStatsDump<'r> {
6187    request: Request<'r>,
6188}
6189impl<'r> OpGetStatsDump<'r> {
6190    pub fn new(mut request: Request<'r>, header: &Nfgenmsg) -> Self {
6191        Self::write_header(request.buf_mut(), header);
6192        Self {
6193            request: request.set_dump(),
6194        }
6195    }
6196    pub fn encode_request<'buf>(
6197        buf: &'buf mut Vec<u8>,
6198        header: &Nfgenmsg,
6199    ) -> PushConntrackStatsAttrs<&'buf mut Vec<u8>> {
6200        Self::write_header(buf, header);
6201        PushConntrackStatsAttrs::new(buf)
6202    }
6203    pub fn encode(&mut self) -> PushConntrackStatsAttrs<&mut Vec<u8>> {
6204        PushConntrackStatsAttrs::new(self.request.buf_mut())
6205    }
6206    pub fn into_encoder(self) -> PushConntrackStatsAttrs<RequestBuf<'r>> {
6207        PushConntrackStatsAttrs::new(self.request.buf)
6208    }
6209    pub fn decode_request<'a>(buf: &'a [u8]) -> (Nfgenmsg, IterableConntrackStatsAttrs<'a>) {
6210        let (header, attrs) = buf.split_at(buf.len().min(Nfgenmsg::len()));
6211        (
6212            Nfgenmsg::new_from_slice(header).unwrap_or_default(),
6213            IterableConntrackStatsAttrs::with_loc(attrs, buf.as_ptr() as usize),
6214        )
6215    }
6216    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Nfgenmsg) {
6217        prev.as_rec_mut().extend(header.as_slice());
6218    }
6219}
6220impl NetlinkRequest for OpGetStatsDump<'_> {
6221    fn protocol(&self) -> Protocol {
6222        Protocol::Raw {
6223            protonum: 12u16,
6224            request_type: 260u16,
6225        }
6226    }
6227    fn flags(&self) -> u16 {
6228        self.request.flags
6229    }
6230    fn payload(&self) -> &[u8] {
6231        self.request.buf()
6232    }
6233    type ReplyType<'buf> = (Nfgenmsg, IterableConntrackStatsAttrs<'buf>);
6234    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6235        Self::decode_request(buf)
6236    }
6237    fn lookup(
6238        buf: &[u8],
6239        offset: usize,
6240        missing_type: Option<u16>,
6241    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6242        Self::decode_request(buf)
6243            .1
6244            .lookup_attr(offset, missing_type)
6245    }
6246}
6247#[derive(Debug)]
6248pub struct ChainedFinal<'a> {
6249    inner: Chained<'a>,
6250}
6251#[derive(Debug)]
6252pub struct Chained<'a> {
6253    buf: RequestBuf<'a>,
6254    first_seq: u32,
6255    lookups: Vec<(&'static str, LookupFn)>,
6256    last_header_offset: usize,
6257    last_kind: Option<RequestInfo>,
6258}
6259impl<'a> ChainedFinal<'a> {
6260    pub fn into_chained(self) -> Chained<'a> {
6261        self.inner
6262    }
6263    pub fn buf(&self) -> &Vec<u8> {
6264        self.inner.buf()
6265    }
6266    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
6267        self.inner.buf_mut()
6268    }
6269    fn get_index(&self, seq: u32) -> Option<u32> {
6270        let min = self.inner.first_seq;
6271        let max = min.wrapping_add(self.inner.lookups.len() as u32);
6272        return if min <= max {
6273            (min..max).contains(&seq).then(|| seq - min)
6274        } else if min <= seq {
6275            Some(seq - min)
6276        } else if seq < max {
6277            Some(u32::MAX - min + seq)
6278        } else {
6279            None
6280        };
6281    }
6282}
6283impl crate::traits::NetlinkChained for ChainedFinal<'_> {
6284    fn protonum(&self) -> u16 {
6285        PROTONUM
6286    }
6287    fn payload(&self) -> &[u8] {
6288        self.buf()
6289    }
6290    fn chain_len(&self) -> usize {
6291        self.inner.lookups.len()
6292    }
6293    fn get_index(&self, seq: u32) -> Option<usize> {
6294        self.get_index(seq).map(|n| n as usize)
6295    }
6296    fn name(&self, index: usize) -> &'static str {
6297        self.inner.lookups[index].0
6298    }
6299    fn lookup(&self, index: usize) -> LookupFn {
6300        self.inner.lookups[index].1
6301    }
6302}
6303impl Chained<'static> {
6304    pub fn new(first_seq: u32) -> Self {
6305        Self::new_from_buf(Vec::new(), first_seq)
6306    }
6307    pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
6308        Self {
6309            buf: RequestBuf::Own(buf),
6310            first_seq,
6311            lookups: Vec::new(),
6312            last_header_offset: 0,
6313            last_kind: None,
6314        }
6315    }
6316    pub fn into_buf(self) -> Vec<u8> {
6317        match self.buf {
6318            RequestBuf::Own(buf) => buf,
6319            _ => unreachable!(),
6320        }
6321    }
6322}
6323impl<'a> Chained<'a> {
6324    pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
6325        Self {
6326            buf: RequestBuf::Ref(buf),
6327            first_seq,
6328            lookups: Vec::new(),
6329            last_header_offset: 0,
6330            last_kind: None,
6331        }
6332    }
6333    pub fn finalize(mut self) -> ChainedFinal<'a> {
6334        self.update_header();
6335        ChainedFinal { inner: self }
6336    }
6337    pub fn request(&mut self) -> Request<'_> {
6338        self.update_header();
6339        self.last_header_offset = self.buf().len();
6340        self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
6341        let mut request = Request::new_extend(self.buf.buf_mut());
6342        self.last_kind = None;
6343        request.writeback = Some(&mut self.last_kind);
6344        request
6345    }
6346    pub fn buf(&self) -> &Vec<u8> {
6347        self.buf.buf()
6348    }
6349    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
6350        self.buf.buf_mut()
6351    }
6352    fn update_header(&mut self) {
6353        let Some(RequestInfo {
6354            protocol,
6355            flags,
6356            name,
6357            lookup,
6358        }) = self.last_kind
6359        else {
6360            if !self.buf().is_empty() {
6361                assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
6362                self.buf.buf_mut().truncate(self.last_header_offset);
6363            }
6364            return;
6365        };
6366        let header_offset = self.last_header_offset;
6367        let request_type = match protocol {
6368            Protocol::Raw { request_type, .. } => request_type,
6369            Protocol::Generic(_) => unreachable!(),
6370        };
6371        let index = self.lookups.len();
6372        let seq = self.first_seq.wrapping_add(index as u32);
6373        self.lookups.push((name, lookup));
6374        let buf = self.buf_mut();
6375        align(buf);
6376        let header = Nlmsghdr {
6377            len: (buf.len() - header_offset) as u32,
6378            r#type: request_type,
6379            flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
6380            seq,
6381            pid: 0,
6382        };
6383        buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
6384    }
6385}
6386use crate::traits::LookupFn;
6387use crate::utils::RequestBuf;
6388#[derive(Debug)]
6389pub struct Request<'buf> {
6390    buf: RequestBuf<'buf>,
6391    flags: u16,
6392    writeback: Option<&'buf mut Option<RequestInfo>>,
6393}
6394#[allow(unused)]
6395#[derive(Debug, Clone)]
6396pub struct RequestInfo {
6397    protocol: Protocol,
6398    flags: u16,
6399    name: &'static str,
6400    lookup: LookupFn,
6401}
6402impl Request<'static> {
6403    pub fn new() -> Self {
6404        Self::new_from_buf(Vec::new())
6405    }
6406    pub fn new_from_buf(buf: Vec<u8>) -> Self {
6407        Self {
6408            flags: 0,
6409            buf: RequestBuf::Own(buf),
6410            writeback: None,
6411        }
6412    }
6413    pub fn into_buf(self) -> Vec<u8> {
6414        match self.buf {
6415            RequestBuf::Own(buf) => buf,
6416            _ => unreachable!(),
6417        }
6418    }
6419}
6420impl<'buf> Request<'buf> {
6421    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
6422        buf.clear();
6423        Self::new_extend(buf)
6424    }
6425    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
6426        Self {
6427            flags: 0,
6428            buf: RequestBuf::Ref(buf),
6429            writeback: None,
6430        }
6431    }
6432    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
6433        let Some(writeback) = &mut self.writeback else {
6434            return;
6435        };
6436        **writeback = Some(RequestInfo {
6437            protocol,
6438            flags: self.flags,
6439            name,
6440            lookup,
6441        })
6442    }
6443    pub fn buf(&self) -> &Vec<u8> {
6444        self.buf.buf()
6445    }
6446    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
6447        self.buf.buf_mut()
6448    }
6449    #[doc = "Set `NLM_F_CREATE` flag"]
6450    pub fn set_create(mut self) -> Self {
6451        self.flags |= consts::NLM_F_CREATE as u16;
6452        self
6453    }
6454    #[doc = "Set `NLM_F_EXCL` flag"]
6455    pub fn set_excl(mut self) -> Self {
6456        self.flags |= consts::NLM_F_EXCL as u16;
6457        self
6458    }
6459    #[doc = "Set `NLM_F_REPLACE` flag"]
6460    pub fn set_replace(mut self) -> Self {
6461        self.flags |= consts::NLM_F_REPLACE as u16;
6462        self
6463    }
6464    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
6465    pub fn set_change(self) -> Self {
6466        self.set_create().set_replace()
6467    }
6468    #[doc = "Set `NLM_F_APPEND` flag"]
6469    pub fn set_append(mut self) -> Self {
6470        self.flags |= consts::NLM_F_APPEND as u16;
6471        self
6472    }
6473    #[doc = "Set `self.flags |= flags`"]
6474    pub fn set_flags(mut self, flags: u16) -> Self {
6475        self.flags |= flags;
6476        self
6477    }
6478    #[doc = "Set `self.flags ^= self.flags & flags`"]
6479    pub fn unset_flags(mut self, flags: u16) -> Self {
6480        self.flags ^= self.flags & flags;
6481        self
6482    }
6483    #[doc = "Set `NLM_F_DUMP` flag"]
6484    fn set_dump(mut self) -> Self {
6485        self.flags |= consts::NLM_F_DUMP as u16;
6486        self
6487    }
6488    #[doc = "get / dump entries\nRequest attributes:\n- [.push_status()](PushConntrackAttrs::push_status)\n- [.push_mark()](PushConntrackAttrs::push_mark)\n- [.push_zone()](PushConntrackAttrs::push_zone)\n- [.nested_filter()](PushConntrackAttrs::nested_filter)\n\nReply attributes:\n- [.get_tuple_orig()](IterableConntrackAttrs::get_tuple_orig)\n- [.get_tuple_reply()](IterableConntrackAttrs::get_tuple_reply)\n- [.get_status()](IterableConntrackAttrs::get_status)\n- [.get_protoinfo()](IterableConntrackAttrs::get_protoinfo)\n- [.get_help()](IterableConntrackAttrs::get_help)\n- [.get_nat_src()](IterableConntrackAttrs::get_nat_src)\n- [.get_timeout()](IterableConntrackAttrs::get_timeout)\n- [.get_mark()](IterableConntrackAttrs::get_mark)\n- [.get_counters_orig()](IterableConntrackAttrs::get_counters_orig)\n- [.get_counters_reply()](IterableConntrackAttrs::get_counters_reply)\n- [.get_use()](IterableConntrackAttrs::get_use)\n- [.get_id()](IterableConntrackAttrs::get_id)\n- [.get_nat_dst()](IterableConntrackAttrs::get_nat_dst)\n- [.get_tuple_master()](IterableConntrackAttrs::get_tuple_master)\n- [.get_seq_adj_orig()](IterableConntrackAttrs::get_seq_adj_orig)\n- [.get_seq_adj_reply()](IterableConntrackAttrs::get_seq_adj_reply)\n- [.get_zone()](IterableConntrackAttrs::get_zone)\n- [.get_secctx()](IterableConntrackAttrs::get_secctx)\n- [.get_labels()](IterableConntrackAttrs::get_labels)\n- [.get_synproxy()](IterableConntrackAttrs::get_synproxy)\n"]
6489    pub fn op_get_dump(self, header: &Nfgenmsg) -> OpGetDump<'buf> {
6490        let mut res = OpGetDump::new(self, header);
6491        res.request
6492            .do_writeback(res.protocol(), "op-get-dump", OpGetDump::lookup);
6493        res
6494    }
6495    #[doc = "get / dump entries\nRequest attributes:\n- [.nested_tuple_orig()](PushConntrackAttrs::nested_tuple_orig)\n- [.nested_tuple_reply()](PushConntrackAttrs::nested_tuple_reply)\n- [.push_zone()](PushConntrackAttrs::push_zone)\n\nReply attributes:\n- [.get_tuple_orig()](IterableConntrackAttrs::get_tuple_orig)\n- [.get_tuple_reply()](IterableConntrackAttrs::get_tuple_reply)\n- [.get_status()](IterableConntrackAttrs::get_status)\n- [.get_protoinfo()](IterableConntrackAttrs::get_protoinfo)\n- [.get_help()](IterableConntrackAttrs::get_help)\n- [.get_nat_src()](IterableConntrackAttrs::get_nat_src)\n- [.get_timeout()](IterableConntrackAttrs::get_timeout)\n- [.get_mark()](IterableConntrackAttrs::get_mark)\n- [.get_counters_orig()](IterableConntrackAttrs::get_counters_orig)\n- [.get_counters_reply()](IterableConntrackAttrs::get_counters_reply)\n- [.get_use()](IterableConntrackAttrs::get_use)\n- [.get_id()](IterableConntrackAttrs::get_id)\n- [.get_nat_dst()](IterableConntrackAttrs::get_nat_dst)\n- [.get_tuple_master()](IterableConntrackAttrs::get_tuple_master)\n- [.get_seq_adj_orig()](IterableConntrackAttrs::get_seq_adj_orig)\n- [.get_seq_adj_reply()](IterableConntrackAttrs::get_seq_adj_reply)\n- [.get_zone()](IterableConntrackAttrs::get_zone)\n- [.get_secctx()](IterableConntrackAttrs::get_secctx)\n- [.get_labels()](IterableConntrackAttrs::get_labels)\n- [.get_synproxy()](IterableConntrackAttrs::get_synproxy)\n"]
6496    pub fn op_get_do(self, header: &Nfgenmsg) -> OpGetDo<'buf> {
6497        let mut res = OpGetDo::new(self, header);
6498        res.request
6499            .do_writeback(res.protocol(), "op-get-do", OpGetDo::lookup);
6500        res
6501    }
6502    #[doc = "dump pcpu conntrack stats\n\nReply attributes:\n- [.get_searched()](IterableConntrackStatsAttrs::get_searched)\n- [.get_found()](IterableConntrackStatsAttrs::get_found)\n- [.get_insert()](IterableConntrackStatsAttrs::get_insert)\n- [.get_insert_failed()](IterableConntrackStatsAttrs::get_insert_failed)\n- [.get_drop()](IterableConntrackStatsAttrs::get_drop)\n- [.get_early_drop()](IterableConntrackStatsAttrs::get_early_drop)\n- [.get_error()](IterableConntrackStatsAttrs::get_error)\n- [.get_search_restart()](IterableConntrackStatsAttrs::get_search_restart)\n- [.get_clash_resolve()](IterableConntrackStatsAttrs::get_clash_resolve)\n- [.get_chain_toolong()](IterableConntrackStatsAttrs::get_chain_toolong)\n"]
6503    pub fn op_get_stats_dump(self, header: &Nfgenmsg) -> OpGetStatsDump<'buf> {
6504        let mut res = OpGetStatsDump::new(self, header);
6505        res.request
6506            .do_writeback(res.protocol(), "op-get-stats-dump", OpGetStatsDump::lookup);
6507        res
6508    }
6509}
6510#[cfg(test)]
6511mod generated_tests {
6512    use super::*;
6513    #[test]
6514    fn tests() {
6515        let _ = IterableConntrackAttrs::get_counters_orig;
6516        let _ = IterableConntrackAttrs::get_counters_reply;
6517        let _ = IterableConntrackAttrs::get_help;
6518        let _ = IterableConntrackAttrs::get_id;
6519        let _ = IterableConntrackAttrs::get_labels;
6520        let _ = IterableConntrackAttrs::get_mark;
6521        let _ = IterableConntrackAttrs::get_nat_dst;
6522        let _ = IterableConntrackAttrs::get_nat_src;
6523        let _ = IterableConntrackAttrs::get_protoinfo;
6524        let _ = IterableConntrackAttrs::get_secctx;
6525        let _ = IterableConntrackAttrs::get_seq_adj_orig;
6526        let _ = IterableConntrackAttrs::get_seq_adj_reply;
6527        let _ = IterableConntrackAttrs::get_status;
6528        let _ = IterableConntrackAttrs::get_synproxy;
6529        let _ = IterableConntrackAttrs::get_timeout;
6530        let _ = IterableConntrackAttrs::get_tuple_master;
6531        let _ = IterableConntrackAttrs::get_tuple_orig;
6532        let _ = IterableConntrackAttrs::get_tuple_reply;
6533        let _ = IterableConntrackAttrs::get_use;
6534        let _ = IterableConntrackAttrs::get_zone;
6535        let _ = IterableConntrackStatsAttrs::get_chain_toolong;
6536        let _ = IterableConntrackStatsAttrs::get_clash_resolve;
6537        let _ = IterableConntrackStatsAttrs::get_drop;
6538        let _ = IterableConntrackStatsAttrs::get_early_drop;
6539        let _ = IterableConntrackStatsAttrs::get_error;
6540        let _ = IterableConntrackStatsAttrs::get_found;
6541        let _ = IterableConntrackStatsAttrs::get_insert;
6542        let _ = IterableConntrackStatsAttrs::get_insert_failed;
6543        let _ = IterableConntrackStatsAttrs::get_search_restart;
6544        let _ = IterableConntrackStatsAttrs::get_searched;
6545        let _ = PushConntrackAttrs::<&mut Vec<u8>>::nested_filter;
6546        let _ = PushConntrackAttrs::<&mut Vec<u8>>::nested_tuple_orig;
6547        let _ = PushConntrackAttrs::<&mut Vec<u8>>::nested_tuple_reply;
6548        let _ = PushConntrackAttrs::<&mut Vec<u8>>::push_mark;
6549        let _ = PushConntrackAttrs::<&mut Vec<u8>>::push_status;
6550        let _ = PushConntrackAttrs::<&mut Vec<u8>>::push_zone;
6551    }
6552}