Skip to main content

netlink_bindings/conntrack/
mod.rs

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