Skip to main content

netlink_bindings/conntrack/
mod.rs

1#![doc = "Netfilter connection tracking subsystem over nfnetlink"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{PushBuiltinBitfield32, PushBuiltinNfgenmsg, PushDummy, PushNlmsghdr};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &CStr = c"conntrack";
17pub const PROTONUM: u16 = 12u16;
18#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
19#[derive(Debug, Clone, Copy)]
20pub enum NfCtTcpFlags {
21    WindowScale = 1 << 0,
22    SackPerm = 1 << 1,
23    CloseInit = 1 << 2,
24    BeLiberal = 1 << 3,
25    Unacked = 1 << 4,
26    Maxack = 1 << 5,
27    ChallengeAck = 1 << 6,
28    SimultaneousOpen = 1 << 7,
29}
30impl NfCtTcpFlags {
31    pub fn from_value(value: u64) -> Option<Self> {
32        Some(match value {
33            n if n == 1 << 0 => Self::WindowScale,
34            n if n == 1 << 1 => Self::SackPerm,
35            n if n == 1 << 2 => Self::CloseInit,
36            n if n == 1 << 3 => Self::BeLiberal,
37            n if n == 1 << 4 => Self::Unacked,
38            n if n == 1 << 5 => Self::Maxack,
39            n if n == 1 << 6 => Self::ChallengeAck,
40            n if n == 1 << 7 => Self::SimultaneousOpen,
41            _ => return None,
42        })
43    }
44}
45#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
46#[derive(Debug, Clone, Copy)]
47pub enum NfCtTcpState {
48    None = 0,
49    SynSent = 1,
50    SynRecv = 2,
51    Established = 3,
52    FinWait = 4,
53    CloseWait = 5,
54    LastAck = 6,
55    TimeWait = 7,
56    Close = 8,
57    SynSent2 = 9,
58    Max = 10,
59    Ignore = 11,
60    Retrans = 12,
61    Unack = 13,
62    TimeoutMax = 14,
63}
64impl NfCtTcpState {
65    pub fn from_value(value: u64) -> Option<Self> {
66        Some(match value {
67            0 => Self::None,
68            1 => Self::SynSent,
69            2 => Self::SynRecv,
70            3 => Self::Established,
71            4 => Self::FinWait,
72            5 => Self::CloseWait,
73            6 => Self::LastAck,
74            7 => Self::TimeWait,
75            8 => Self::Close,
76            9 => Self::SynSent2,
77            10 => Self::Max,
78            11 => Self::Ignore,
79            12 => Self::Retrans,
80            13 => Self::Unack,
81            14 => Self::TimeoutMax,
82            _ => return None,
83        })
84    }
85}
86#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
87#[derive(Debug, Clone, Copy)]
88pub enum NfCtSctpState {
89    None = 0,
90    Cloned = 1,
91    CookieWait = 2,
92    CookieEchoed = 3,
93    Established = 4,
94    ShutdownSent = 5,
95    ShutdownReceived = 6,
96    ShutdownAckSent = 7,
97    ShutdownHeartbeatSent = 8,
98}
99impl NfCtSctpState {
100    pub fn from_value(value: u64) -> Option<Self> {
101        Some(match value {
102            0 => Self::None,
103            1 => Self::Cloned,
104            2 => Self::CookieWait,
105            3 => Self::CookieEchoed,
106            4 => Self::Established,
107            5 => Self::ShutdownSent,
108            6 => Self::ShutdownReceived,
109            7 => Self::ShutdownAckSent,
110            8 => Self::ShutdownHeartbeatSent,
111            _ => return None,
112        })
113    }
114}
115#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
116#[derive(Debug, Clone, Copy)]
117pub enum NfCtStatus {
118    Expected = 1 << 0,
119    SeenReply = 1 << 1,
120    Assured = 1 << 2,
121    Confirmed = 1 << 3,
122    SrcNat = 1 << 4,
123    DstNat = 1 << 5,
124    SeqAdj = 1 << 6,
125    SrcNatDone = 1 << 7,
126    DstNatDone = 1 << 8,
127    Dying = 1 << 9,
128    FixedTimeout = 1 << 10,
129    Template = 1 << 11,
130    NatClash = 1 << 12,
131    Helper = 1 << 13,
132    Offload = 1 << 14,
133    HwOffload = 1 << 15,
134}
135impl NfCtStatus {
136    pub fn from_value(value: u64) -> Option<Self> {
137        Some(match value {
138            n if n == 1 << 0 => Self::Expected,
139            n if n == 1 << 1 => Self::SeenReply,
140            n if n == 1 << 2 => Self::Assured,
141            n if n == 1 << 3 => Self::Confirmed,
142            n if n == 1 << 4 => Self::SrcNat,
143            n if n == 1 << 5 => Self::DstNat,
144            n if n == 1 << 6 => Self::SeqAdj,
145            n if n == 1 << 7 => Self::SrcNatDone,
146            n if n == 1 << 8 => Self::DstNatDone,
147            n if n == 1 << 9 => Self::Dying,
148            n if n == 1 << 10 => Self::FixedTimeout,
149            n if n == 1 << 11 => Self::Template,
150            n if n == 1 << 12 => Self::NatClash,
151            n if n == 1 << 13 => Self::Helper,
152            n if n == 1 << 14 => Self::Offload,
153            n if n == 1 << 15 => Self::HwOffload,
154            _ => return None,
155        })
156    }
157}
158#[derive(Clone)]
159pub enum CounterAttrs<'a> {
160    Packets(u64),
161    Bytes(u64),
162    PacketsOld(u32),
163    BytesOld(u32),
164    Pad(&'a [u8]),
165}
166impl<'a> IterableCounterAttrs<'a> {
167    pub fn get_packets(&self) -> Result<u64, ErrorContext> {
168        let mut iter = self.clone();
169        iter.pos = 0;
170        for attr in iter {
171            if let CounterAttrs::Packets(val) = attr? {
172                return Ok(val);
173            }
174        }
175        Err(ErrorContext::new_missing(
176            "CounterAttrs",
177            "Packets",
178            self.orig_loc,
179            self.buf.as_ptr() as usize,
180        ))
181    }
182    pub fn get_bytes(&self) -> Result<u64, ErrorContext> {
183        let mut iter = self.clone();
184        iter.pos = 0;
185        for attr in iter {
186            if let CounterAttrs::Bytes(val) = attr? {
187                return Ok(val);
188            }
189        }
190        Err(ErrorContext::new_missing(
191            "CounterAttrs",
192            "Bytes",
193            self.orig_loc,
194            self.buf.as_ptr() as usize,
195        ))
196    }
197    pub fn get_packets_old(&self) -> Result<u32, ErrorContext> {
198        let mut iter = self.clone();
199        iter.pos = 0;
200        for attr in iter {
201            if let CounterAttrs::PacketsOld(val) = attr? {
202                return Ok(val);
203            }
204        }
205        Err(ErrorContext::new_missing(
206            "CounterAttrs",
207            "PacketsOld",
208            self.orig_loc,
209            self.buf.as_ptr() as usize,
210        ))
211    }
212    pub fn get_bytes_old(&self) -> Result<u32, ErrorContext> {
213        let mut iter = self.clone();
214        iter.pos = 0;
215        for attr in iter {
216            if let CounterAttrs::BytesOld(val) = attr? {
217                return Ok(val);
218            }
219        }
220        Err(ErrorContext::new_missing(
221            "CounterAttrs",
222            "BytesOld",
223            self.orig_loc,
224            self.buf.as_ptr() as usize,
225        ))
226    }
227    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
228        let mut iter = self.clone();
229        iter.pos = 0;
230        for attr in iter {
231            if let CounterAttrs::Pad(val) = attr? {
232                return Ok(val);
233            }
234        }
235        Err(ErrorContext::new_missing(
236            "CounterAttrs",
237            "Pad",
238            self.orig_loc,
239            self.buf.as_ptr() as usize,
240        ))
241    }
242}
243impl CounterAttrs<'_> {
244    pub fn new<'a>(buf: &'a [u8]) -> IterableCounterAttrs<'a> {
245        IterableCounterAttrs::with_loc(buf, buf.as_ptr() as usize)
246    }
247    fn attr_from_type(r#type: u16) -> Option<&'static str> {
248        let res = match r#type {
249            1u16 => "Packets",
250            2u16 => "Bytes",
251            3u16 => "PacketsOld",
252            4u16 => "BytesOld",
253            5u16 => "Pad",
254            _ => return None,
255        };
256        Some(res)
257    }
258}
259#[derive(Clone, Copy, Default)]
260pub struct IterableCounterAttrs<'a> {
261    buf: &'a [u8],
262    pos: usize,
263    orig_loc: usize,
264}
265impl<'a> IterableCounterAttrs<'a> {
266    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
267        Self {
268            buf,
269            pos: 0,
270            orig_loc,
271        }
272    }
273    pub fn get_buf(&self) -> &'a [u8] {
274        self.buf
275    }
276}
277impl<'a> Iterator for IterableCounterAttrs<'a> {
278    type Item = Result<CounterAttrs<'a>, ErrorContext>;
279    fn next(&mut self) -> Option<Self::Item> {
280        let pos = self.pos;
281        let mut r#type;
282        loop {
283            r#type = None;
284            if self.buf.len() == self.pos {
285                return None;
286            }
287            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
288                break;
289            };
290            r#type = Some(header.r#type);
291            let res = match header.r#type {
292                1u16 => CounterAttrs::Packets({
293                    let res = parse_be_u64(next);
294                    let Some(val) = res else { break };
295                    val
296                }),
297                2u16 => CounterAttrs::Bytes({
298                    let res = parse_be_u64(next);
299                    let Some(val) = res else { break };
300                    val
301                }),
302                3u16 => CounterAttrs::PacketsOld({
303                    let res = parse_u32(next);
304                    let Some(val) = res else { break };
305                    val
306                }),
307                4u16 => CounterAttrs::BytesOld({
308                    let res = parse_u32(next);
309                    let Some(val) = res else { break };
310                    val
311                }),
312                5u16 => CounterAttrs::Pad({
313                    let res = Some(next);
314                    let Some(val) = res else { break };
315                    val
316                }),
317                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
318                n => continue,
319            };
320            return Some(Ok(res));
321        }
322        Some(Err(ErrorContext::new(
323            "CounterAttrs",
324            r#type.and_then(|t| CounterAttrs::attr_from_type(t)),
325            self.orig_loc,
326            self.buf.as_ptr().wrapping_add(pos) as usize,
327        )))
328    }
329}
330impl<'a> std::fmt::Debug for IterableCounterAttrs<'_> {
331    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
332        let mut fmt = f.debug_struct("CounterAttrs");
333        for attr in self.clone() {
334            let attr = match attr {
335                Ok(a) => a,
336                Err(err) => {
337                    fmt.finish()?;
338                    f.write_str("Err(")?;
339                    err.fmt(f)?;
340                    return f.write_str(")");
341                }
342            };
343            match attr {
344                CounterAttrs::Packets(val) => fmt.field("Packets", &val),
345                CounterAttrs::Bytes(val) => fmt.field("Bytes", &val),
346                CounterAttrs::PacketsOld(val) => fmt.field("PacketsOld", &val),
347                CounterAttrs::BytesOld(val) => fmt.field("BytesOld", &val),
348                CounterAttrs::Pad(val) => fmt.field("Pad", &val),
349            };
350        }
351        fmt.finish()
352    }
353}
354impl IterableCounterAttrs<'_> {
355    pub fn lookup_attr(
356        &self,
357        offset: usize,
358        missing_type: Option<u16>,
359    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
360        let mut stack = Vec::new();
361        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
362        if cur == offset {
363            stack.push(("CounterAttrs", offset));
364            return (
365                stack,
366                missing_type.and_then(|t| CounterAttrs::attr_from_type(t)),
367            );
368        }
369        if cur > offset || cur + self.buf.len() < offset {
370            return (stack, None);
371        }
372        let mut attrs = self.clone();
373        let mut last_off = cur + attrs.pos;
374        while let Some(attr) = attrs.next() {
375            let Ok(attr) = attr else { break };
376            match attr {
377                CounterAttrs::Packets(val) => {
378                    if last_off == offset {
379                        stack.push(("Packets", last_off));
380                        break;
381                    }
382                }
383                CounterAttrs::Bytes(val) => {
384                    if last_off == offset {
385                        stack.push(("Bytes", last_off));
386                        break;
387                    }
388                }
389                CounterAttrs::PacketsOld(val) => {
390                    if last_off == offset {
391                        stack.push(("PacketsOld", last_off));
392                        break;
393                    }
394                }
395                CounterAttrs::BytesOld(val) => {
396                    if last_off == offset {
397                        stack.push(("BytesOld", last_off));
398                        break;
399                    }
400                }
401                CounterAttrs::Pad(val) => {
402                    if last_off == offset {
403                        stack.push(("Pad", last_off));
404                        break;
405                    }
406                }
407                _ => {}
408            };
409            last_off = cur + attrs.pos;
410        }
411        if !stack.is_empty() {
412            stack.push(("CounterAttrs", cur));
413        }
414        (stack, None)
415    }
416}
417#[derive(Clone)]
418pub enum TupleProtoAttrs {
419    #[doc = "l4 protocol number"]
420    ProtoNum(u8),
421    #[doc = "l4 source port"]
422    ProtoSrcPort(u16),
423    #[doc = "l4 source port"]
424    ProtoDstPort(u16),
425    #[doc = "l4 icmp id"]
426    ProtoIcmpId(u16),
427    ProtoIcmpType(u8),
428    ProtoIcmpCode(u8),
429    #[doc = "l4 icmp id"]
430    ProtoIcmpv6Id(u16),
431    ProtoIcmpv6Type(u8),
432    ProtoIcmpv6Code(u8),
433}
434impl<'a> IterableTupleProtoAttrs<'a> {
435    #[doc = "l4 protocol number"]
436    pub fn get_proto_num(&self) -> Result<u8, ErrorContext> {
437        let mut iter = self.clone();
438        iter.pos = 0;
439        for attr in iter {
440            if let TupleProtoAttrs::ProtoNum(val) = attr? {
441                return Ok(val);
442            }
443        }
444        Err(ErrorContext::new_missing(
445            "TupleProtoAttrs",
446            "ProtoNum",
447            self.orig_loc,
448            self.buf.as_ptr() as usize,
449        ))
450    }
451    #[doc = "l4 source port"]
452    pub fn get_proto_src_port(&self) -> Result<u16, ErrorContext> {
453        let mut iter = self.clone();
454        iter.pos = 0;
455        for attr in iter {
456            if let TupleProtoAttrs::ProtoSrcPort(val) = attr? {
457                return Ok(val);
458            }
459        }
460        Err(ErrorContext::new_missing(
461            "TupleProtoAttrs",
462            "ProtoSrcPort",
463            self.orig_loc,
464            self.buf.as_ptr() as usize,
465        ))
466    }
467    #[doc = "l4 source port"]
468    pub fn get_proto_dst_port(&self) -> Result<u16, ErrorContext> {
469        let mut iter = self.clone();
470        iter.pos = 0;
471        for attr in iter {
472            if let TupleProtoAttrs::ProtoDstPort(val) = attr? {
473                return Ok(val);
474            }
475        }
476        Err(ErrorContext::new_missing(
477            "TupleProtoAttrs",
478            "ProtoDstPort",
479            self.orig_loc,
480            self.buf.as_ptr() as usize,
481        ))
482    }
483    #[doc = "l4 icmp id"]
484    pub fn get_proto_icmp_id(&self) -> Result<u16, ErrorContext> {
485        let mut iter = self.clone();
486        iter.pos = 0;
487        for attr in iter {
488            if let TupleProtoAttrs::ProtoIcmpId(val) = attr? {
489                return Ok(val);
490            }
491        }
492        Err(ErrorContext::new_missing(
493            "TupleProtoAttrs",
494            "ProtoIcmpId",
495            self.orig_loc,
496            self.buf.as_ptr() as usize,
497        ))
498    }
499    pub fn get_proto_icmp_type(&self) -> Result<u8, ErrorContext> {
500        let mut iter = self.clone();
501        iter.pos = 0;
502        for attr in iter {
503            if let TupleProtoAttrs::ProtoIcmpType(val) = attr? {
504                return Ok(val);
505            }
506        }
507        Err(ErrorContext::new_missing(
508            "TupleProtoAttrs",
509            "ProtoIcmpType",
510            self.orig_loc,
511            self.buf.as_ptr() as usize,
512        ))
513    }
514    pub fn get_proto_icmp_code(&self) -> Result<u8, ErrorContext> {
515        let mut iter = self.clone();
516        iter.pos = 0;
517        for attr in iter {
518            if let TupleProtoAttrs::ProtoIcmpCode(val) = attr? {
519                return Ok(val);
520            }
521        }
522        Err(ErrorContext::new_missing(
523            "TupleProtoAttrs",
524            "ProtoIcmpCode",
525            self.orig_loc,
526            self.buf.as_ptr() as usize,
527        ))
528    }
529    #[doc = "l4 icmp id"]
530    pub fn get_proto_icmpv6_id(&self) -> Result<u16, ErrorContext> {
531        let mut iter = self.clone();
532        iter.pos = 0;
533        for attr in iter {
534            if let TupleProtoAttrs::ProtoIcmpv6Id(val) = attr? {
535                return Ok(val);
536            }
537        }
538        Err(ErrorContext::new_missing(
539            "TupleProtoAttrs",
540            "ProtoIcmpv6Id",
541            self.orig_loc,
542            self.buf.as_ptr() as usize,
543        ))
544    }
545    pub fn get_proto_icmpv6_type(&self) -> Result<u8, ErrorContext> {
546        let mut iter = self.clone();
547        iter.pos = 0;
548        for attr in iter {
549            if let TupleProtoAttrs::ProtoIcmpv6Type(val) = attr? {
550                return Ok(val);
551            }
552        }
553        Err(ErrorContext::new_missing(
554            "TupleProtoAttrs",
555            "ProtoIcmpv6Type",
556            self.orig_loc,
557            self.buf.as_ptr() as usize,
558        ))
559    }
560    pub fn get_proto_icmpv6_code(&self) -> Result<u8, ErrorContext> {
561        let mut iter = self.clone();
562        iter.pos = 0;
563        for attr in iter {
564            if let TupleProtoAttrs::ProtoIcmpv6Code(val) = attr? {
565                return Ok(val);
566            }
567        }
568        Err(ErrorContext::new_missing(
569            "TupleProtoAttrs",
570            "ProtoIcmpv6Code",
571            self.orig_loc,
572            self.buf.as_ptr() as usize,
573        ))
574    }
575}
576impl TupleProtoAttrs {
577    pub fn new<'a>(buf: &'a [u8]) -> IterableTupleProtoAttrs<'a> {
578        IterableTupleProtoAttrs::with_loc(buf, buf.as_ptr() as usize)
579    }
580    fn attr_from_type(r#type: u16) -> Option<&'static str> {
581        let res = match r#type {
582            1u16 => "ProtoNum",
583            2u16 => "ProtoSrcPort",
584            3u16 => "ProtoDstPort",
585            4u16 => "ProtoIcmpId",
586            5u16 => "ProtoIcmpType",
587            6u16 => "ProtoIcmpCode",
588            7u16 => "ProtoIcmpv6Id",
589            8u16 => "ProtoIcmpv6Type",
590            9u16 => "ProtoIcmpv6Code",
591            _ => return None,
592        };
593        Some(res)
594    }
595}
596#[derive(Clone, Copy, Default)]
597pub struct IterableTupleProtoAttrs<'a> {
598    buf: &'a [u8],
599    pos: usize,
600    orig_loc: usize,
601}
602impl<'a> IterableTupleProtoAttrs<'a> {
603    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
604        Self {
605            buf,
606            pos: 0,
607            orig_loc,
608        }
609    }
610    pub fn get_buf(&self) -> &'a [u8] {
611        self.buf
612    }
613}
614impl<'a> Iterator for IterableTupleProtoAttrs<'a> {
615    type Item = Result<TupleProtoAttrs, ErrorContext>;
616    fn next(&mut self) -> Option<Self::Item> {
617        let pos = self.pos;
618        let mut r#type;
619        loop {
620            r#type = None;
621            if self.buf.len() == self.pos {
622                return None;
623            }
624            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
625                break;
626            };
627            r#type = Some(header.r#type);
628            let res = match header.r#type {
629                1u16 => TupleProtoAttrs::ProtoNum({
630                    let res = parse_u8(next);
631                    let Some(val) = res else { break };
632                    val
633                }),
634                2u16 => TupleProtoAttrs::ProtoSrcPort({
635                    let res = parse_be_u16(next);
636                    let Some(val) = res else { break };
637                    val
638                }),
639                3u16 => TupleProtoAttrs::ProtoDstPort({
640                    let res = parse_be_u16(next);
641                    let Some(val) = res else { break };
642                    val
643                }),
644                4u16 => TupleProtoAttrs::ProtoIcmpId({
645                    let res = parse_be_u16(next);
646                    let Some(val) = res else { break };
647                    val
648                }),
649                5u16 => TupleProtoAttrs::ProtoIcmpType({
650                    let res = parse_u8(next);
651                    let Some(val) = res else { break };
652                    val
653                }),
654                6u16 => TupleProtoAttrs::ProtoIcmpCode({
655                    let res = parse_u8(next);
656                    let Some(val) = res else { break };
657                    val
658                }),
659                7u16 => TupleProtoAttrs::ProtoIcmpv6Id({
660                    let res = parse_be_u16(next);
661                    let Some(val) = res else { break };
662                    val
663                }),
664                8u16 => TupleProtoAttrs::ProtoIcmpv6Type({
665                    let res = parse_u8(next);
666                    let Some(val) = res else { break };
667                    val
668                }),
669                9u16 => TupleProtoAttrs::ProtoIcmpv6Code({
670                    let res = parse_u8(next);
671                    let Some(val) = res else { break };
672                    val
673                }),
674                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
675                n => continue,
676            };
677            return Some(Ok(res));
678        }
679        Some(Err(ErrorContext::new(
680            "TupleProtoAttrs",
681            r#type.and_then(|t| TupleProtoAttrs::attr_from_type(t)),
682            self.orig_loc,
683            self.buf.as_ptr().wrapping_add(pos) as usize,
684        )))
685    }
686}
687impl std::fmt::Debug for IterableTupleProtoAttrs<'_> {
688    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
689        let mut fmt = f.debug_struct("TupleProtoAttrs");
690        for attr in self.clone() {
691            let attr = match attr {
692                Ok(a) => a,
693                Err(err) => {
694                    fmt.finish()?;
695                    f.write_str("Err(")?;
696                    err.fmt(f)?;
697                    return f.write_str(")");
698                }
699            };
700            match attr {
701                TupleProtoAttrs::ProtoNum(val) => fmt.field("ProtoNum", &val),
702                TupleProtoAttrs::ProtoSrcPort(val) => fmt.field("ProtoSrcPort", &val),
703                TupleProtoAttrs::ProtoDstPort(val) => fmt.field("ProtoDstPort", &val),
704                TupleProtoAttrs::ProtoIcmpId(val) => fmt.field("ProtoIcmpId", &val),
705                TupleProtoAttrs::ProtoIcmpType(val) => fmt.field("ProtoIcmpType", &val),
706                TupleProtoAttrs::ProtoIcmpCode(val) => fmt.field("ProtoIcmpCode", &val),
707                TupleProtoAttrs::ProtoIcmpv6Id(val) => fmt.field("ProtoIcmpv6Id", &val),
708                TupleProtoAttrs::ProtoIcmpv6Type(val) => fmt.field("ProtoIcmpv6Type", &val),
709                TupleProtoAttrs::ProtoIcmpv6Code(val) => fmt.field("ProtoIcmpv6Code", &val),
710            };
711        }
712        fmt.finish()
713    }
714}
715impl IterableTupleProtoAttrs<'_> {
716    pub fn lookup_attr(
717        &self,
718        offset: usize,
719        missing_type: Option<u16>,
720    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
721        let mut stack = Vec::new();
722        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
723        if cur == offset {
724            stack.push(("TupleProtoAttrs", offset));
725            return (
726                stack,
727                missing_type.and_then(|t| TupleProtoAttrs::attr_from_type(t)),
728            );
729        }
730        if cur > offset || cur + self.buf.len() < offset {
731            return (stack, None);
732        }
733        let mut attrs = self.clone();
734        let mut last_off = cur + attrs.pos;
735        while let Some(attr) = attrs.next() {
736            let Ok(attr) = attr else { break };
737            match attr {
738                TupleProtoAttrs::ProtoNum(val) => {
739                    if last_off == offset {
740                        stack.push(("ProtoNum", last_off));
741                        break;
742                    }
743                }
744                TupleProtoAttrs::ProtoSrcPort(val) => {
745                    if last_off == offset {
746                        stack.push(("ProtoSrcPort", last_off));
747                        break;
748                    }
749                }
750                TupleProtoAttrs::ProtoDstPort(val) => {
751                    if last_off == offset {
752                        stack.push(("ProtoDstPort", last_off));
753                        break;
754                    }
755                }
756                TupleProtoAttrs::ProtoIcmpId(val) => {
757                    if last_off == offset {
758                        stack.push(("ProtoIcmpId", last_off));
759                        break;
760                    }
761                }
762                TupleProtoAttrs::ProtoIcmpType(val) => {
763                    if last_off == offset {
764                        stack.push(("ProtoIcmpType", last_off));
765                        break;
766                    }
767                }
768                TupleProtoAttrs::ProtoIcmpCode(val) => {
769                    if last_off == offset {
770                        stack.push(("ProtoIcmpCode", last_off));
771                        break;
772                    }
773                }
774                TupleProtoAttrs::ProtoIcmpv6Id(val) => {
775                    if last_off == offset {
776                        stack.push(("ProtoIcmpv6Id", last_off));
777                        break;
778                    }
779                }
780                TupleProtoAttrs::ProtoIcmpv6Type(val) => {
781                    if last_off == offset {
782                        stack.push(("ProtoIcmpv6Type", last_off));
783                        break;
784                    }
785                }
786                TupleProtoAttrs::ProtoIcmpv6Code(val) => {
787                    if last_off == offset {
788                        stack.push(("ProtoIcmpv6Code", last_off));
789                        break;
790                    }
791                }
792                _ => {}
793            };
794            last_off = cur + attrs.pos;
795        }
796        if !stack.is_empty() {
797            stack.push(("TupleProtoAttrs", cur));
798        }
799        (stack, None)
800    }
801}
802#[derive(Clone)]
803pub enum TupleIpAttrs {
804    #[doc = "ipv4 source address"]
805    IpV4Src(std::net::Ipv4Addr),
806    #[doc = "ipv4 destination address"]
807    IpV4Dst(std::net::Ipv4Addr),
808    #[doc = "ipv6 source address"]
809    IpV6Src(std::net::Ipv6Addr),
810    #[doc = "ipv6 destination address"]
811    IpV6Dst(std::net::Ipv6Addr),
812}
813impl<'a> IterableTupleIpAttrs<'a> {
814    #[doc = "ipv4 source address"]
815    pub fn get_ip_v4_src(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
816        let mut iter = self.clone();
817        iter.pos = 0;
818        for attr in iter {
819            if let TupleIpAttrs::IpV4Src(val) = attr? {
820                return Ok(val);
821            }
822        }
823        Err(ErrorContext::new_missing(
824            "TupleIpAttrs",
825            "IpV4Src",
826            self.orig_loc,
827            self.buf.as_ptr() as usize,
828        ))
829    }
830    #[doc = "ipv4 destination address"]
831    pub fn get_ip_v4_dst(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
832        let mut iter = self.clone();
833        iter.pos = 0;
834        for attr in iter {
835            if let TupleIpAttrs::IpV4Dst(val) = attr? {
836                return Ok(val);
837            }
838        }
839        Err(ErrorContext::new_missing(
840            "TupleIpAttrs",
841            "IpV4Dst",
842            self.orig_loc,
843            self.buf.as_ptr() as usize,
844        ))
845    }
846    #[doc = "ipv6 source address"]
847    pub fn get_ip_v6_src(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
848        let mut iter = self.clone();
849        iter.pos = 0;
850        for attr in iter {
851            if let TupleIpAttrs::IpV6Src(val) = attr? {
852                return Ok(val);
853            }
854        }
855        Err(ErrorContext::new_missing(
856            "TupleIpAttrs",
857            "IpV6Src",
858            self.orig_loc,
859            self.buf.as_ptr() as usize,
860        ))
861    }
862    #[doc = "ipv6 destination address"]
863    pub fn get_ip_v6_dst(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
864        let mut iter = self.clone();
865        iter.pos = 0;
866        for attr in iter {
867            if let TupleIpAttrs::IpV6Dst(val) = attr? {
868                return Ok(val);
869            }
870        }
871        Err(ErrorContext::new_missing(
872            "TupleIpAttrs",
873            "IpV6Dst",
874            self.orig_loc,
875            self.buf.as_ptr() as usize,
876        ))
877    }
878}
879impl TupleIpAttrs {
880    pub fn new<'a>(buf: &'a [u8]) -> IterableTupleIpAttrs<'a> {
881        IterableTupleIpAttrs::with_loc(buf, buf.as_ptr() as usize)
882    }
883    fn attr_from_type(r#type: u16) -> Option<&'static str> {
884        let res = match r#type {
885            1u16 => "IpV4Src",
886            2u16 => "IpV4Dst",
887            3u16 => "IpV6Src",
888            4u16 => "IpV6Dst",
889            _ => return None,
890        };
891        Some(res)
892    }
893}
894#[derive(Clone, Copy, Default)]
895pub struct IterableTupleIpAttrs<'a> {
896    buf: &'a [u8],
897    pos: usize,
898    orig_loc: usize,
899}
900impl<'a> IterableTupleIpAttrs<'a> {
901    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
902        Self {
903            buf,
904            pos: 0,
905            orig_loc,
906        }
907    }
908    pub fn get_buf(&self) -> &'a [u8] {
909        self.buf
910    }
911}
912impl<'a> Iterator for IterableTupleIpAttrs<'a> {
913    type Item = Result<TupleIpAttrs, ErrorContext>;
914    fn next(&mut self) -> Option<Self::Item> {
915        let pos = self.pos;
916        let mut r#type;
917        loop {
918            r#type = None;
919            if self.buf.len() == self.pos {
920                return None;
921            }
922            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
923                break;
924            };
925            r#type = Some(header.r#type);
926            let res = match header.r#type {
927                1u16 => TupleIpAttrs::IpV4Src({
928                    let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
929                    let Some(val) = res else { break };
930                    val
931                }),
932                2u16 => TupleIpAttrs::IpV4Dst({
933                    let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
934                    let Some(val) = res else { break };
935                    val
936                }),
937                3u16 => TupleIpAttrs::IpV6Src({
938                    let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
939                    let Some(val) = res else { break };
940                    val
941                }),
942                4u16 => TupleIpAttrs::IpV6Dst({
943                    let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
944                    let Some(val) = res else { break };
945                    val
946                }),
947                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
948                n => continue,
949            };
950            return Some(Ok(res));
951        }
952        Some(Err(ErrorContext::new(
953            "TupleIpAttrs",
954            r#type.and_then(|t| TupleIpAttrs::attr_from_type(t)),
955            self.orig_loc,
956            self.buf.as_ptr().wrapping_add(pos) as usize,
957        )))
958    }
959}
960impl std::fmt::Debug for IterableTupleIpAttrs<'_> {
961    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
962        let mut fmt = f.debug_struct("TupleIpAttrs");
963        for attr in self.clone() {
964            let attr = match attr {
965                Ok(a) => a,
966                Err(err) => {
967                    fmt.finish()?;
968                    f.write_str("Err(")?;
969                    err.fmt(f)?;
970                    return f.write_str(")");
971                }
972            };
973            match attr {
974                TupleIpAttrs::IpV4Src(val) => fmt.field("IpV4Src", &val),
975                TupleIpAttrs::IpV4Dst(val) => fmt.field("IpV4Dst", &val),
976                TupleIpAttrs::IpV6Src(val) => fmt.field("IpV6Src", &val),
977                TupleIpAttrs::IpV6Dst(val) => fmt.field("IpV6Dst", &val),
978            };
979        }
980        fmt.finish()
981    }
982}
983impl IterableTupleIpAttrs<'_> {
984    pub fn lookup_attr(
985        &self,
986        offset: usize,
987        missing_type: Option<u16>,
988    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
989        let mut stack = Vec::new();
990        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
991        if cur == offset {
992            stack.push(("TupleIpAttrs", offset));
993            return (
994                stack,
995                missing_type.and_then(|t| TupleIpAttrs::attr_from_type(t)),
996            );
997        }
998        if cur > offset || cur + self.buf.len() < offset {
999            return (stack, None);
1000        }
1001        let mut attrs = self.clone();
1002        let mut last_off = cur + attrs.pos;
1003        while let Some(attr) = attrs.next() {
1004            let Ok(attr) = attr else { break };
1005            match attr {
1006                TupleIpAttrs::IpV4Src(val) => {
1007                    if last_off == offset {
1008                        stack.push(("IpV4Src", last_off));
1009                        break;
1010                    }
1011                }
1012                TupleIpAttrs::IpV4Dst(val) => {
1013                    if last_off == offset {
1014                        stack.push(("IpV4Dst", last_off));
1015                        break;
1016                    }
1017                }
1018                TupleIpAttrs::IpV6Src(val) => {
1019                    if last_off == offset {
1020                        stack.push(("IpV6Src", last_off));
1021                        break;
1022                    }
1023                }
1024                TupleIpAttrs::IpV6Dst(val) => {
1025                    if last_off == offset {
1026                        stack.push(("IpV6Dst", last_off));
1027                        break;
1028                    }
1029                }
1030                _ => {}
1031            };
1032            last_off = cur + attrs.pos;
1033        }
1034        if !stack.is_empty() {
1035            stack.push(("TupleIpAttrs", cur));
1036        }
1037        (stack, None)
1038    }
1039}
1040#[derive(Clone)]
1041pub enum TupleAttrs<'a> {
1042    #[doc = "conntrack l3 information"]
1043    TupleIp(IterableTupleIpAttrs<'a>),
1044    #[doc = "conntrack l4 information"]
1045    TupleProto(IterableTupleProtoAttrs<'a>),
1046    #[doc = "conntrack zone id"]
1047    TupleZone(u16),
1048}
1049impl<'a> IterableTupleAttrs<'a> {
1050    #[doc = "conntrack l3 information"]
1051    pub fn get_tuple_ip(&self) -> Result<IterableTupleIpAttrs<'a>, ErrorContext> {
1052        let mut iter = self.clone();
1053        iter.pos = 0;
1054        for attr in iter {
1055            if let TupleAttrs::TupleIp(val) = attr? {
1056                return Ok(val);
1057            }
1058        }
1059        Err(ErrorContext::new_missing(
1060            "TupleAttrs",
1061            "TupleIp",
1062            self.orig_loc,
1063            self.buf.as_ptr() as usize,
1064        ))
1065    }
1066    #[doc = "conntrack l4 information"]
1067    pub fn get_tuple_proto(&self) -> Result<IterableTupleProtoAttrs<'a>, ErrorContext> {
1068        let mut iter = self.clone();
1069        iter.pos = 0;
1070        for attr in iter {
1071            if let TupleAttrs::TupleProto(val) = attr? {
1072                return Ok(val);
1073            }
1074        }
1075        Err(ErrorContext::new_missing(
1076            "TupleAttrs",
1077            "TupleProto",
1078            self.orig_loc,
1079            self.buf.as_ptr() as usize,
1080        ))
1081    }
1082    #[doc = "conntrack zone id"]
1083    pub fn get_tuple_zone(&self) -> Result<u16, ErrorContext> {
1084        let mut iter = self.clone();
1085        iter.pos = 0;
1086        for attr in iter {
1087            if let TupleAttrs::TupleZone(val) = attr? {
1088                return Ok(val);
1089            }
1090        }
1091        Err(ErrorContext::new_missing(
1092            "TupleAttrs",
1093            "TupleZone",
1094            self.orig_loc,
1095            self.buf.as_ptr() as usize,
1096        ))
1097    }
1098}
1099impl TupleAttrs<'_> {
1100    pub fn new<'a>(buf: &'a [u8]) -> IterableTupleAttrs<'a> {
1101        IterableTupleAttrs::with_loc(buf, buf.as_ptr() as usize)
1102    }
1103    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1104        let res = match r#type {
1105            1u16 => "TupleIp",
1106            2u16 => "TupleProto",
1107            3u16 => "TupleZone",
1108            _ => return None,
1109        };
1110        Some(res)
1111    }
1112}
1113#[derive(Clone, Copy, Default)]
1114pub struct IterableTupleAttrs<'a> {
1115    buf: &'a [u8],
1116    pos: usize,
1117    orig_loc: usize,
1118}
1119impl<'a> IterableTupleAttrs<'a> {
1120    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1121        Self {
1122            buf,
1123            pos: 0,
1124            orig_loc,
1125        }
1126    }
1127    pub fn get_buf(&self) -> &'a [u8] {
1128        self.buf
1129    }
1130}
1131impl<'a> Iterator for IterableTupleAttrs<'a> {
1132    type Item = Result<TupleAttrs<'a>, ErrorContext>;
1133    fn next(&mut self) -> Option<Self::Item> {
1134        let pos = self.pos;
1135        let mut r#type;
1136        loop {
1137            r#type = None;
1138            if self.buf.len() == self.pos {
1139                return None;
1140            }
1141            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1142                break;
1143            };
1144            r#type = Some(header.r#type);
1145            let res = match header.r#type {
1146                1u16 => TupleAttrs::TupleIp({
1147                    let res = Some(IterableTupleIpAttrs::with_loc(next, self.orig_loc));
1148                    let Some(val) = res else { break };
1149                    val
1150                }),
1151                2u16 => TupleAttrs::TupleProto({
1152                    let res = Some(IterableTupleProtoAttrs::with_loc(next, self.orig_loc));
1153                    let Some(val) = res else { break };
1154                    val
1155                }),
1156                3u16 => TupleAttrs::TupleZone({
1157                    let res = parse_be_u16(next);
1158                    let Some(val) = res else { break };
1159                    val
1160                }),
1161                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1162                n => continue,
1163            };
1164            return Some(Ok(res));
1165        }
1166        Some(Err(ErrorContext::new(
1167            "TupleAttrs",
1168            r#type.and_then(|t| TupleAttrs::attr_from_type(t)),
1169            self.orig_loc,
1170            self.buf.as_ptr().wrapping_add(pos) as usize,
1171        )))
1172    }
1173}
1174impl<'a> std::fmt::Debug for IterableTupleAttrs<'_> {
1175    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1176        let mut fmt = f.debug_struct("TupleAttrs");
1177        for attr in self.clone() {
1178            let attr = match attr {
1179                Ok(a) => a,
1180                Err(err) => {
1181                    fmt.finish()?;
1182                    f.write_str("Err(")?;
1183                    err.fmt(f)?;
1184                    return f.write_str(")");
1185                }
1186            };
1187            match attr {
1188                TupleAttrs::TupleIp(val) => fmt.field("TupleIp", &val),
1189                TupleAttrs::TupleProto(val) => fmt.field("TupleProto", &val),
1190                TupleAttrs::TupleZone(val) => fmt.field("TupleZone", &val),
1191            };
1192        }
1193        fmt.finish()
1194    }
1195}
1196impl IterableTupleAttrs<'_> {
1197    pub fn lookup_attr(
1198        &self,
1199        offset: usize,
1200        missing_type: Option<u16>,
1201    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1202        let mut stack = Vec::new();
1203        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1204        if cur == offset {
1205            stack.push(("TupleAttrs", offset));
1206            return (
1207                stack,
1208                missing_type.and_then(|t| TupleAttrs::attr_from_type(t)),
1209            );
1210        }
1211        if cur > offset || cur + self.buf.len() < offset {
1212            return (stack, None);
1213        }
1214        let mut attrs = self.clone();
1215        let mut last_off = cur + attrs.pos;
1216        let mut missing = None;
1217        while let Some(attr) = attrs.next() {
1218            let Ok(attr) = attr else { break };
1219            match attr {
1220                TupleAttrs::TupleIp(val) => {
1221                    (stack, missing) = val.lookup_attr(offset, missing_type);
1222                    if !stack.is_empty() {
1223                        break;
1224                    }
1225                }
1226                TupleAttrs::TupleProto(val) => {
1227                    (stack, missing) = val.lookup_attr(offset, missing_type);
1228                    if !stack.is_empty() {
1229                        break;
1230                    }
1231                }
1232                TupleAttrs::TupleZone(val) => {
1233                    if last_off == offset {
1234                        stack.push(("TupleZone", last_off));
1235                        break;
1236                    }
1237                }
1238                _ => {}
1239            };
1240            last_off = cur + attrs.pos;
1241        }
1242        if !stack.is_empty() {
1243            stack.push(("TupleAttrs", cur));
1244        }
1245        (stack, missing)
1246    }
1247}
1248#[derive(Clone)]
1249pub enum ProtoinfoTcpAttrs {
1250    #[doc = "tcp connection state\nAssociated type: \"NfCtTcpState\" (enum)"]
1251    TcpState(u8),
1252    #[doc = "window scaling factor in original direction"]
1253    TcpWscaleOriginal(u8),
1254    #[doc = "window scaling factor in reply direction"]
1255    TcpWscaleReply(u8),
1256    TcpFlagsOriginal(PushNfCtTcpFlagsMask),
1257    TcpFlagsReply(PushNfCtTcpFlagsMask),
1258}
1259impl<'a> IterableProtoinfoTcpAttrs<'a> {
1260    #[doc = "tcp connection state\nAssociated type: \"NfCtTcpState\" (enum)"]
1261    pub fn get_tcp_state(&self) -> Result<u8, ErrorContext> {
1262        let mut iter = self.clone();
1263        iter.pos = 0;
1264        for attr in iter {
1265            if let ProtoinfoTcpAttrs::TcpState(val) = attr? {
1266                return Ok(val);
1267            }
1268        }
1269        Err(ErrorContext::new_missing(
1270            "ProtoinfoTcpAttrs",
1271            "TcpState",
1272            self.orig_loc,
1273            self.buf.as_ptr() as usize,
1274        ))
1275    }
1276    #[doc = "window scaling factor in original direction"]
1277    pub fn get_tcp_wscale_original(&self) -> Result<u8, ErrorContext> {
1278        let mut iter = self.clone();
1279        iter.pos = 0;
1280        for attr in iter {
1281            if let ProtoinfoTcpAttrs::TcpWscaleOriginal(val) = attr? {
1282                return Ok(val);
1283            }
1284        }
1285        Err(ErrorContext::new_missing(
1286            "ProtoinfoTcpAttrs",
1287            "TcpWscaleOriginal",
1288            self.orig_loc,
1289            self.buf.as_ptr() as usize,
1290        ))
1291    }
1292    #[doc = "window scaling factor in reply direction"]
1293    pub fn get_tcp_wscale_reply(&self) -> Result<u8, ErrorContext> {
1294        let mut iter = self.clone();
1295        iter.pos = 0;
1296        for attr in iter {
1297            if let ProtoinfoTcpAttrs::TcpWscaleReply(val) = attr? {
1298                return Ok(val);
1299            }
1300        }
1301        Err(ErrorContext::new_missing(
1302            "ProtoinfoTcpAttrs",
1303            "TcpWscaleReply",
1304            self.orig_loc,
1305            self.buf.as_ptr() as usize,
1306        ))
1307    }
1308    pub fn get_tcp_flags_original(&self) -> Result<PushNfCtTcpFlagsMask, ErrorContext> {
1309        let mut iter = self.clone();
1310        iter.pos = 0;
1311        for attr in iter {
1312            if let ProtoinfoTcpAttrs::TcpFlagsOriginal(val) = attr? {
1313                return Ok(val);
1314            }
1315        }
1316        Err(ErrorContext::new_missing(
1317            "ProtoinfoTcpAttrs",
1318            "TcpFlagsOriginal",
1319            self.orig_loc,
1320            self.buf.as_ptr() as usize,
1321        ))
1322    }
1323    pub fn get_tcp_flags_reply(&self) -> Result<PushNfCtTcpFlagsMask, ErrorContext> {
1324        let mut iter = self.clone();
1325        iter.pos = 0;
1326        for attr in iter {
1327            if let ProtoinfoTcpAttrs::TcpFlagsReply(val) = attr? {
1328                return Ok(val);
1329            }
1330        }
1331        Err(ErrorContext::new_missing(
1332            "ProtoinfoTcpAttrs",
1333            "TcpFlagsReply",
1334            self.orig_loc,
1335            self.buf.as_ptr() as usize,
1336        ))
1337    }
1338}
1339impl ProtoinfoTcpAttrs {
1340    pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoTcpAttrs<'a> {
1341        IterableProtoinfoTcpAttrs::with_loc(buf, buf.as_ptr() as usize)
1342    }
1343    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1344        let res = match r#type {
1345            1u16 => "TcpState",
1346            2u16 => "TcpWscaleOriginal",
1347            3u16 => "TcpWscaleReply",
1348            4u16 => "TcpFlagsOriginal",
1349            5u16 => "TcpFlagsReply",
1350            _ => return None,
1351        };
1352        Some(res)
1353    }
1354}
1355#[derive(Clone, Copy, Default)]
1356pub struct IterableProtoinfoTcpAttrs<'a> {
1357    buf: &'a [u8],
1358    pos: usize,
1359    orig_loc: usize,
1360}
1361impl<'a> IterableProtoinfoTcpAttrs<'a> {
1362    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1363        Self {
1364            buf,
1365            pos: 0,
1366            orig_loc,
1367        }
1368    }
1369    pub fn get_buf(&self) -> &'a [u8] {
1370        self.buf
1371    }
1372}
1373impl<'a> Iterator for IterableProtoinfoTcpAttrs<'a> {
1374    type Item = Result<ProtoinfoTcpAttrs, ErrorContext>;
1375    fn next(&mut self) -> Option<Self::Item> {
1376        let pos = self.pos;
1377        let mut r#type;
1378        loop {
1379            r#type = None;
1380            if self.buf.len() == self.pos {
1381                return None;
1382            }
1383            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1384                break;
1385            };
1386            r#type = Some(header.r#type);
1387            let res = match header.r#type {
1388                1u16 => ProtoinfoTcpAttrs::TcpState({
1389                    let res = parse_u8(next);
1390                    let Some(val) = res else { break };
1391                    val
1392                }),
1393                2u16 => ProtoinfoTcpAttrs::TcpWscaleOriginal({
1394                    let res = parse_u8(next);
1395                    let Some(val) = res else { break };
1396                    val
1397                }),
1398                3u16 => ProtoinfoTcpAttrs::TcpWscaleReply({
1399                    let res = parse_u8(next);
1400                    let Some(val) = res else { break };
1401                    val
1402                }),
1403                4u16 => ProtoinfoTcpAttrs::TcpFlagsOriginal({
1404                    let res = PushNfCtTcpFlagsMask::new_from_slice(next);
1405                    let Some(val) = res else { break };
1406                    val
1407                }),
1408                5u16 => ProtoinfoTcpAttrs::TcpFlagsReply({
1409                    let res = PushNfCtTcpFlagsMask::new_from_slice(next);
1410                    let Some(val) = res else { break };
1411                    val
1412                }),
1413                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1414                n => continue,
1415            };
1416            return Some(Ok(res));
1417        }
1418        Some(Err(ErrorContext::new(
1419            "ProtoinfoTcpAttrs",
1420            r#type.and_then(|t| ProtoinfoTcpAttrs::attr_from_type(t)),
1421            self.orig_loc,
1422            self.buf.as_ptr().wrapping_add(pos) as usize,
1423        )))
1424    }
1425}
1426impl std::fmt::Debug for IterableProtoinfoTcpAttrs<'_> {
1427    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1428        let mut fmt = f.debug_struct("ProtoinfoTcpAttrs");
1429        for attr in self.clone() {
1430            let attr = match attr {
1431                Ok(a) => a,
1432                Err(err) => {
1433                    fmt.finish()?;
1434                    f.write_str("Err(")?;
1435                    err.fmt(f)?;
1436                    return f.write_str(")");
1437                }
1438            };
1439            match attr {
1440                ProtoinfoTcpAttrs::TcpState(val) => fmt.field(
1441                    "TcpState",
1442                    &FormatEnum(val.into(), NfCtTcpState::from_value),
1443                ),
1444                ProtoinfoTcpAttrs::TcpWscaleOriginal(val) => fmt.field("TcpWscaleOriginal", &val),
1445                ProtoinfoTcpAttrs::TcpWscaleReply(val) => fmt.field("TcpWscaleReply", &val),
1446                ProtoinfoTcpAttrs::TcpFlagsOriginal(val) => fmt.field("TcpFlagsOriginal", &val),
1447                ProtoinfoTcpAttrs::TcpFlagsReply(val) => fmt.field("TcpFlagsReply", &val),
1448            };
1449        }
1450        fmt.finish()
1451    }
1452}
1453impl IterableProtoinfoTcpAttrs<'_> {
1454    pub fn lookup_attr(
1455        &self,
1456        offset: usize,
1457        missing_type: Option<u16>,
1458    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1459        let mut stack = Vec::new();
1460        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1461        if cur == offset {
1462            stack.push(("ProtoinfoTcpAttrs", offset));
1463            return (
1464                stack,
1465                missing_type.and_then(|t| ProtoinfoTcpAttrs::attr_from_type(t)),
1466            );
1467        }
1468        if cur > offset || cur + self.buf.len() < offset {
1469            return (stack, None);
1470        }
1471        let mut attrs = self.clone();
1472        let mut last_off = cur + attrs.pos;
1473        while let Some(attr) = attrs.next() {
1474            let Ok(attr) = attr else { break };
1475            match attr {
1476                ProtoinfoTcpAttrs::TcpState(val) => {
1477                    if last_off == offset {
1478                        stack.push(("TcpState", last_off));
1479                        break;
1480                    }
1481                }
1482                ProtoinfoTcpAttrs::TcpWscaleOriginal(val) => {
1483                    if last_off == offset {
1484                        stack.push(("TcpWscaleOriginal", last_off));
1485                        break;
1486                    }
1487                }
1488                ProtoinfoTcpAttrs::TcpWscaleReply(val) => {
1489                    if last_off == offset {
1490                        stack.push(("TcpWscaleReply", last_off));
1491                        break;
1492                    }
1493                }
1494                ProtoinfoTcpAttrs::TcpFlagsOriginal(val) => {
1495                    if last_off == offset {
1496                        stack.push(("TcpFlagsOriginal", last_off));
1497                        break;
1498                    }
1499                }
1500                ProtoinfoTcpAttrs::TcpFlagsReply(val) => {
1501                    if last_off == offset {
1502                        stack.push(("TcpFlagsReply", last_off));
1503                        break;
1504                    }
1505                }
1506                _ => {}
1507            };
1508            last_off = cur + attrs.pos;
1509        }
1510        if !stack.is_empty() {
1511            stack.push(("ProtoinfoTcpAttrs", cur));
1512        }
1513        (stack, None)
1514    }
1515}
1516#[derive(Clone)]
1517pub enum ProtoinfoDccpAttrs<'a> {
1518    #[doc = "dccp connection state"]
1519    DccpState(u8),
1520    DccpRole(u8),
1521    DccpHandshakeSeq(u64),
1522    DccpPad(&'a [u8]),
1523}
1524impl<'a> IterableProtoinfoDccpAttrs<'a> {
1525    #[doc = "dccp connection state"]
1526    pub fn get_dccp_state(&self) -> Result<u8, ErrorContext> {
1527        let mut iter = self.clone();
1528        iter.pos = 0;
1529        for attr in iter {
1530            if let ProtoinfoDccpAttrs::DccpState(val) = attr? {
1531                return Ok(val);
1532            }
1533        }
1534        Err(ErrorContext::new_missing(
1535            "ProtoinfoDccpAttrs",
1536            "DccpState",
1537            self.orig_loc,
1538            self.buf.as_ptr() as usize,
1539        ))
1540    }
1541    pub fn get_dccp_role(&self) -> Result<u8, ErrorContext> {
1542        let mut iter = self.clone();
1543        iter.pos = 0;
1544        for attr in iter {
1545            if let ProtoinfoDccpAttrs::DccpRole(val) = attr? {
1546                return Ok(val);
1547            }
1548        }
1549        Err(ErrorContext::new_missing(
1550            "ProtoinfoDccpAttrs",
1551            "DccpRole",
1552            self.orig_loc,
1553            self.buf.as_ptr() as usize,
1554        ))
1555    }
1556    pub fn get_dccp_handshake_seq(&self) -> Result<u64, ErrorContext> {
1557        let mut iter = self.clone();
1558        iter.pos = 0;
1559        for attr in iter {
1560            if let ProtoinfoDccpAttrs::DccpHandshakeSeq(val) = attr? {
1561                return Ok(val);
1562            }
1563        }
1564        Err(ErrorContext::new_missing(
1565            "ProtoinfoDccpAttrs",
1566            "DccpHandshakeSeq",
1567            self.orig_loc,
1568            self.buf.as_ptr() as usize,
1569        ))
1570    }
1571    pub fn get_dccp_pad(&self) -> Result<&'a [u8], ErrorContext> {
1572        let mut iter = self.clone();
1573        iter.pos = 0;
1574        for attr in iter {
1575            if let ProtoinfoDccpAttrs::DccpPad(val) = attr? {
1576                return Ok(val);
1577            }
1578        }
1579        Err(ErrorContext::new_missing(
1580            "ProtoinfoDccpAttrs",
1581            "DccpPad",
1582            self.orig_loc,
1583            self.buf.as_ptr() as usize,
1584        ))
1585    }
1586}
1587impl ProtoinfoDccpAttrs<'_> {
1588    pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoDccpAttrs<'a> {
1589        IterableProtoinfoDccpAttrs::with_loc(buf, buf.as_ptr() as usize)
1590    }
1591    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1592        let res = match r#type {
1593            1u16 => "DccpState",
1594            2u16 => "DccpRole",
1595            3u16 => "DccpHandshakeSeq",
1596            4u16 => "DccpPad",
1597            _ => return None,
1598        };
1599        Some(res)
1600    }
1601}
1602#[derive(Clone, Copy, Default)]
1603pub struct IterableProtoinfoDccpAttrs<'a> {
1604    buf: &'a [u8],
1605    pos: usize,
1606    orig_loc: usize,
1607}
1608impl<'a> IterableProtoinfoDccpAttrs<'a> {
1609    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1610        Self {
1611            buf,
1612            pos: 0,
1613            orig_loc,
1614        }
1615    }
1616    pub fn get_buf(&self) -> &'a [u8] {
1617        self.buf
1618    }
1619}
1620impl<'a> Iterator for IterableProtoinfoDccpAttrs<'a> {
1621    type Item = Result<ProtoinfoDccpAttrs<'a>, ErrorContext>;
1622    fn next(&mut self) -> Option<Self::Item> {
1623        let pos = self.pos;
1624        let mut r#type;
1625        loop {
1626            r#type = None;
1627            if self.buf.len() == self.pos {
1628                return None;
1629            }
1630            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1631                break;
1632            };
1633            r#type = Some(header.r#type);
1634            let res = match header.r#type {
1635                1u16 => ProtoinfoDccpAttrs::DccpState({
1636                    let res = parse_u8(next);
1637                    let Some(val) = res else { break };
1638                    val
1639                }),
1640                2u16 => ProtoinfoDccpAttrs::DccpRole({
1641                    let res = parse_u8(next);
1642                    let Some(val) = res else { break };
1643                    val
1644                }),
1645                3u16 => ProtoinfoDccpAttrs::DccpHandshakeSeq({
1646                    let res = parse_be_u64(next);
1647                    let Some(val) = res else { break };
1648                    val
1649                }),
1650                4u16 => ProtoinfoDccpAttrs::DccpPad({
1651                    let res = Some(next);
1652                    let Some(val) = res else { break };
1653                    val
1654                }),
1655                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1656                n => continue,
1657            };
1658            return Some(Ok(res));
1659        }
1660        Some(Err(ErrorContext::new(
1661            "ProtoinfoDccpAttrs",
1662            r#type.and_then(|t| ProtoinfoDccpAttrs::attr_from_type(t)),
1663            self.orig_loc,
1664            self.buf.as_ptr().wrapping_add(pos) as usize,
1665        )))
1666    }
1667}
1668impl<'a> std::fmt::Debug for IterableProtoinfoDccpAttrs<'_> {
1669    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1670        let mut fmt = f.debug_struct("ProtoinfoDccpAttrs");
1671        for attr in self.clone() {
1672            let attr = match attr {
1673                Ok(a) => a,
1674                Err(err) => {
1675                    fmt.finish()?;
1676                    f.write_str("Err(")?;
1677                    err.fmt(f)?;
1678                    return f.write_str(")");
1679                }
1680            };
1681            match attr {
1682                ProtoinfoDccpAttrs::DccpState(val) => fmt.field("DccpState", &val),
1683                ProtoinfoDccpAttrs::DccpRole(val) => fmt.field("DccpRole", &val),
1684                ProtoinfoDccpAttrs::DccpHandshakeSeq(val) => fmt.field("DccpHandshakeSeq", &val),
1685                ProtoinfoDccpAttrs::DccpPad(val) => fmt.field("DccpPad", &val),
1686            };
1687        }
1688        fmt.finish()
1689    }
1690}
1691impl IterableProtoinfoDccpAttrs<'_> {
1692    pub fn lookup_attr(
1693        &self,
1694        offset: usize,
1695        missing_type: Option<u16>,
1696    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1697        let mut stack = Vec::new();
1698        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1699        if cur == offset {
1700            stack.push(("ProtoinfoDccpAttrs", offset));
1701            return (
1702                stack,
1703                missing_type.and_then(|t| ProtoinfoDccpAttrs::attr_from_type(t)),
1704            );
1705        }
1706        if cur > offset || cur + self.buf.len() < offset {
1707            return (stack, None);
1708        }
1709        let mut attrs = self.clone();
1710        let mut last_off = cur + attrs.pos;
1711        while let Some(attr) = attrs.next() {
1712            let Ok(attr) = attr else { break };
1713            match attr {
1714                ProtoinfoDccpAttrs::DccpState(val) => {
1715                    if last_off == offset {
1716                        stack.push(("DccpState", last_off));
1717                        break;
1718                    }
1719                }
1720                ProtoinfoDccpAttrs::DccpRole(val) => {
1721                    if last_off == offset {
1722                        stack.push(("DccpRole", last_off));
1723                        break;
1724                    }
1725                }
1726                ProtoinfoDccpAttrs::DccpHandshakeSeq(val) => {
1727                    if last_off == offset {
1728                        stack.push(("DccpHandshakeSeq", last_off));
1729                        break;
1730                    }
1731                }
1732                ProtoinfoDccpAttrs::DccpPad(val) => {
1733                    if last_off == offset {
1734                        stack.push(("DccpPad", last_off));
1735                        break;
1736                    }
1737                }
1738                _ => {}
1739            };
1740            last_off = cur + attrs.pos;
1741        }
1742        if !stack.is_empty() {
1743            stack.push(("ProtoinfoDccpAttrs", cur));
1744        }
1745        (stack, None)
1746    }
1747}
1748#[derive(Clone)]
1749pub enum ProtoinfoSctpAttrs {
1750    #[doc = "sctp connection state\nAssociated type: \"NfCtSctpState\" (enum)"]
1751    SctpState(u8),
1752    VtagOriginal(u32),
1753    VtagReply(u32),
1754}
1755impl<'a> IterableProtoinfoSctpAttrs<'a> {
1756    #[doc = "sctp connection state\nAssociated type: \"NfCtSctpState\" (enum)"]
1757    pub fn get_sctp_state(&self) -> Result<u8, ErrorContext> {
1758        let mut iter = self.clone();
1759        iter.pos = 0;
1760        for attr in iter {
1761            if let ProtoinfoSctpAttrs::SctpState(val) = attr? {
1762                return Ok(val);
1763            }
1764        }
1765        Err(ErrorContext::new_missing(
1766            "ProtoinfoSctpAttrs",
1767            "SctpState",
1768            self.orig_loc,
1769            self.buf.as_ptr() as usize,
1770        ))
1771    }
1772    pub fn get_vtag_original(&self) -> Result<u32, ErrorContext> {
1773        let mut iter = self.clone();
1774        iter.pos = 0;
1775        for attr in iter {
1776            if let ProtoinfoSctpAttrs::VtagOriginal(val) = attr? {
1777                return Ok(val);
1778            }
1779        }
1780        Err(ErrorContext::new_missing(
1781            "ProtoinfoSctpAttrs",
1782            "VtagOriginal",
1783            self.orig_loc,
1784            self.buf.as_ptr() as usize,
1785        ))
1786    }
1787    pub fn get_vtag_reply(&self) -> Result<u32, ErrorContext> {
1788        let mut iter = self.clone();
1789        iter.pos = 0;
1790        for attr in iter {
1791            if let ProtoinfoSctpAttrs::VtagReply(val) = attr? {
1792                return Ok(val);
1793            }
1794        }
1795        Err(ErrorContext::new_missing(
1796            "ProtoinfoSctpAttrs",
1797            "VtagReply",
1798            self.orig_loc,
1799            self.buf.as_ptr() as usize,
1800        ))
1801    }
1802}
1803impl ProtoinfoSctpAttrs {
1804    pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoSctpAttrs<'a> {
1805        IterableProtoinfoSctpAttrs::with_loc(buf, buf.as_ptr() as usize)
1806    }
1807    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1808        let res = match r#type {
1809            1u16 => "SctpState",
1810            2u16 => "VtagOriginal",
1811            3u16 => "VtagReply",
1812            _ => return None,
1813        };
1814        Some(res)
1815    }
1816}
1817#[derive(Clone, Copy, Default)]
1818pub struct IterableProtoinfoSctpAttrs<'a> {
1819    buf: &'a [u8],
1820    pos: usize,
1821    orig_loc: usize,
1822}
1823impl<'a> IterableProtoinfoSctpAttrs<'a> {
1824    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1825        Self {
1826            buf,
1827            pos: 0,
1828            orig_loc,
1829        }
1830    }
1831    pub fn get_buf(&self) -> &'a [u8] {
1832        self.buf
1833    }
1834}
1835impl<'a> Iterator for IterableProtoinfoSctpAttrs<'a> {
1836    type Item = Result<ProtoinfoSctpAttrs, ErrorContext>;
1837    fn next(&mut self) -> Option<Self::Item> {
1838        let pos = self.pos;
1839        let mut r#type;
1840        loop {
1841            r#type = None;
1842            if self.buf.len() == self.pos {
1843                return None;
1844            }
1845            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1846                break;
1847            };
1848            r#type = Some(header.r#type);
1849            let res = match header.r#type {
1850                1u16 => ProtoinfoSctpAttrs::SctpState({
1851                    let res = parse_u8(next);
1852                    let Some(val) = res else { break };
1853                    val
1854                }),
1855                2u16 => ProtoinfoSctpAttrs::VtagOriginal({
1856                    let res = parse_be_u32(next);
1857                    let Some(val) = res else { break };
1858                    val
1859                }),
1860                3u16 => ProtoinfoSctpAttrs::VtagReply({
1861                    let res = parse_be_u32(next);
1862                    let Some(val) = res else { break };
1863                    val
1864                }),
1865                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1866                n => continue,
1867            };
1868            return Some(Ok(res));
1869        }
1870        Some(Err(ErrorContext::new(
1871            "ProtoinfoSctpAttrs",
1872            r#type.and_then(|t| ProtoinfoSctpAttrs::attr_from_type(t)),
1873            self.orig_loc,
1874            self.buf.as_ptr().wrapping_add(pos) as usize,
1875        )))
1876    }
1877}
1878impl std::fmt::Debug for IterableProtoinfoSctpAttrs<'_> {
1879    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1880        let mut fmt = f.debug_struct("ProtoinfoSctpAttrs");
1881        for attr in self.clone() {
1882            let attr = match attr {
1883                Ok(a) => a,
1884                Err(err) => {
1885                    fmt.finish()?;
1886                    f.write_str("Err(")?;
1887                    err.fmt(f)?;
1888                    return f.write_str(")");
1889                }
1890            };
1891            match attr {
1892                ProtoinfoSctpAttrs::SctpState(val) => fmt.field(
1893                    "SctpState",
1894                    &FormatEnum(val.into(), NfCtSctpState::from_value),
1895                ),
1896                ProtoinfoSctpAttrs::VtagOriginal(val) => fmt.field("VtagOriginal", &val),
1897                ProtoinfoSctpAttrs::VtagReply(val) => fmt.field("VtagReply", &val),
1898            };
1899        }
1900        fmt.finish()
1901    }
1902}
1903impl IterableProtoinfoSctpAttrs<'_> {
1904    pub fn lookup_attr(
1905        &self,
1906        offset: usize,
1907        missing_type: Option<u16>,
1908    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1909        let mut stack = Vec::new();
1910        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1911        if cur == offset {
1912            stack.push(("ProtoinfoSctpAttrs", offset));
1913            return (
1914                stack,
1915                missing_type.and_then(|t| ProtoinfoSctpAttrs::attr_from_type(t)),
1916            );
1917        }
1918        if cur > offset || cur + self.buf.len() < offset {
1919            return (stack, None);
1920        }
1921        let mut attrs = self.clone();
1922        let mut last_off = cur + attrs.pos;
1923        while let Some(attr) = attrs.next() {
1924            let Ok(attr) = attr else { break };
1925            match attr {
1926                ProtoinfoSctpAttrs::SctpState(val) => {
1927                    if last_off == offset {
1928                        stack.push(("SctpState", last_off));
1929                        break;
1930                    }
1931                }
1932                ProtoinfoSctpAttrs::VtagOriginal(val) => {
1933                    if last_off == offset {
1934                        stack.push(("VtagOriginal", last_off));
1935                        break;
1936                    }
1937                }
1938                ProtoinfoSctpAttrs::VtagReply(val) => {
1939                    if last_off == offset {
1940                        stack.push(("VtagReply", last_off));
1941                        break;
1942                    }
1943                }
1944                _ => {}
1945            };
1946            last_off = cur + attrs.pos;
1947        }
1948        if !stack.is_empty() {
1949            stack.push(("ProtoinfoSctpAttrs", cur));
1950        }
1951        (stack, None)
1952    }
1953}
1954#[derive(Clone)]
1955pub enum ProtoinfoAttrs<'a> {
1956    #[doc = "conntrack tcp state information"]
1957    ProtoinfoTcp(IterableProtoinfoTcpAttrs<'a>),
1958    #[doc = "conntrack dccp state information"]
1959    ProtoinfoDccp(IterableProtoinfoDccpAttrs<'a>),
1960    #[doc = "conntrack sctp state information"]
1961    ProtoinfoSctp(IterableProtoinfoSctpAttrs<'a>),
1962}
1963impl<'a> IterableProtoinfoAttrs<'a> {
1964    #[doc = "conntrack tcp state information"]
1965    pub fn get_protoinfo_tcp(&self) -> Result<IterableProtoinfoTcpAttrs<'a>, ErrorContext> {
1966        let mut iter = self.clone();
1967        iter.pos = 0;
1968        for attr in iter {
1969            if let ProtoinfoAttrs::ProtoinfoTcp(val) = attr? {
1970                return Ok(val);
1971            }
1972        }
1973        Err(ErrorContext::new_missing(
1974            "ProtoinfoAttrs",
1975            "ProtoinfoTcp",
1976            self.orig_loc,
1977            self.buf.as_ptr() as usize,
1978        ))
1979    }
1980    #[doc = "conntrack dccp state information"]
1981    pub fn get_protoinfo_dccp(&self) -> Result<IterableProtoinfoDccpAttrs<'a>, ErrorContext> {
1982        let mut iter = self.clone();
1983        iter.pos = 0;
1984        for attr in iter {
1985            if let ProtoinfoAttrs::ProtoinfoDccp(val) = attr? {
1986                return Ok(val);
1987            }
1988        }
1989        Err(ErrorContext::new_missing(
1990            "ProtoinfoAttrs",
1991            "ProtoinfoDccp",
1992            self.orig_loc,
1993            self.buf.as_ptr() as usize,
1994        ))
1995    }
1996    #[doc = "conntrack sctp state information"]
1997    pub fn get_protoinfo_sctp(&self) -> Result<IterableProtoinfoSctpAttrs<'a>, ErrorContext> {
1998        let mut iter = self.clone();
1999        iter.pos = 0;
2000        for attr in iter {
2001            if let ProtoinfoAttrs::ProtoinfoSctp(val) = attr? {
2002                return Ok(val);
2003            }
2004        }
2005        Err(ErrorContext::new_missing(
2006            "ProtoinfoAttrs",
2007            "ProtoinfoSctp",
2008            self.orig_loc,
2009            self.buf.as_ptr() as usize,
2010        ))
2011    }
2012}
2013impl ProtoinfoAttrs<'_> {
2014    pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoAttrs<'a> {
2015        IterableProtoinfoAttrs::with_loc(buf, buf.as_ptr() as usize)
2016    }
2017    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2018        let res = match r#type {
2019            1u16 => "ProtoinfoTcp",
2020            2u16 => "ProtoinfoDccp",
2021            3u16 => "ProtoinfoSctp",
2022            _ => return None,
2023        };
2024        Some(res)
2025    }
2026}
2027#[derive(Clone, Copy, Default)]
2028pub struct IterableProtoinfoAttrs<'a> {
2029    buf: &'a [u8],
2030    pos: usize,
2031    orig_loc: usize,
2032}
2033impl<'a> IterableProtoinfoAttrs<'a> {
2034    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2035        Self {
2036            buf,
2037            pos: 0,
2038            orig_loc,
2039        }
2040    }
2041    pub fn get_buf(&self) -> &'a [u8] {
2042        self.buf
2043    }
2044}
2045impl<'a> Iterator for IterableProtoinfoAttrs<'a> {
2046    type Item = Result<ProtoinfoAttrs<'a>, ErrorContext>;
2047    fn next(&mut self) -> Option<Self::Item> {
2048        let pos = self.pos;
2049        let mut r#type;
2050        loop {
2051            r#type = None;
2052            if self.buf.len() == self.pos {
2053                return None;
2054            }
2055            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2056                break;
2057            };
2058            r#type = Some(header.r#type);
2059            let res = match header.r#type {
2060                1u16 => ProtoinfoAttrs::ProtoinfoTcp({
2061                    let res = Some(IterableProtoinfoTcpAttrs::with_loc(next, self.orig_loc));
2062                    let Some(val) = res else { break };
2063                    val
2064                }),
2065                2u16 => ProtoinfoAttrs::ProtoinfoDccp({
2066                    let res = Some(IterableProtoinfoDccpAttrs::with_loc(next, self.orig_loc));
2067                    let Some(val) = res else { break };
2068                    val
2069                }),
2070                3u16 => ProtoinfoAttrs::ProtoinfoSctp({
2071                    let res = Some(IterableProtoinfoSctpAttrs::with_loc(next, self.orig_loc));
2072                    let Some(val) = res else { break };
2073                    val
2074                }),
2075                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2076                n => continue,
2077            };
2078            return Some(Ok(res));
2079        }
2080        Some(Err(ErrorContext::new(
2081            "ProtoinfoAttrs",
2082            r#type.and_then(|t| ProtoinfoAttrs::attr_from_type(t)),
2083            self.orig_loc,
2084            self.buf.as_ptr().wrapping_add(pos) as usize,
2085        )))
2086    }
2087}
2088impl<'a> std::fmt::Debug for IterableProtoinfoAttrs<'_> {
2089    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2090        let mut fmt = f.debug_struct("ProtoinfoAttrs");
2091        for attr in self.clone() {
2092            let attr = match attr {
2093                Ok(a) => a,
2094                Err(err) => {
2095                    fmt.finish()?;
2096                    f.write_str("Err(")?;
2097                    err.fmt(f)?;
2098                    return f.write_str(")");
2099                }
2100            };
2101            match attr {
2102                ProtoinfoAttrs::ProtoinfoTcp(val) => fmt.field("ProtoinfoTcp", &val),
2103                ProtoinfoAttrs::ProtoinfoDccp(val) => fmt.field("ProtoinfoDccp", &val),
2104                ProtoinfoAttrs::ProtoinfoSctp(val) => fmt.field("ProtoinfoSctp", &val),
2105            };
2106        }
2107        fmt.finish()
2108    }
2109}
2110impl IterableProtoinfoAttrs<'_> {
2111    pub fn lookup_attr(
2112        &self,
2113        offset: usize,
2114        missing_type: Option<u16>,
2115    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2116        let mut stack = Vec::new();
2117        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2118        if cur == offset {
2119            stack.push(("ProtoinfoAttrs", offset));
2120            return (
2121                stack,
2122                missing_type.and_then(|t| ProtoinfoAttrs::attr_from_type(t)),
2123            );
2124        }
2125        if cur > offset || cur + self.buf.len() < offset {
2126            return (stack, None);
2127        }
2128        let mut attrs = self.clone();
2129        let mut last_off = cur + attrs.pos;
2130        let mut missing = None;
2131        while let Some(attr) = attrs.next() {
2132            let Ok(attr) = attr else { break };
2133            match attr {
2134                ProtoinfoAttrs::ProtoinfoTcp(val) => {
2135                    (stack, missing) = val.lookup_attr(offset, missing_type);
2136                    if !stack.is_empty() {
2137                        break;
2138                    }
2139                }
2140                ProtoinfoAttrs::ProtoinfoDccp(val) => {
2141                    (stack, missing) = val.lookup_attr(offset, missing_type);
2142                    if !stack.is_empty() {
2143                        break;
2144                    }
2145                }
2146                ProtoinfoAttrs::ProtoinfoSctp(val) => {
2147                    (stack, missing) = val.lookup_attr(offset, missing_type);
2148                    if !stack.is_empty() {
2149                        break;
2150                    }
2151                }
2152                _ => {}
2153            };
2154            last_off = cur + attrs.pos;
2155        }
2156        if !stack.is_empty() {
2157            stack.push(("ProtoinfoAttrs", cur));
2158        }
2159        (stack, missing)
2160    }
2161}
2162#[derive(Clone)]
2163pub enum HelpAttrs<'a> {
2164    #[doc = "helper name"]
2165    HelpName(&'a CStr),
2166}
2167impl<'a> IterableHelpAttrs<'a> {
2168    #[doc = "helper name"]
2169    pub fn get_help_name(&self) -> Result<&'a CStr, ErrorContext> {
2170        let mut iter = self.clone();
2171        iter.pos = 0;
2172        for attr in iter {
2173            if let HelpAttrs::HelpName(val) = attr? {
2174                return Ok(val);
2175            }
2176        }
2177        Err(ErrorContext::new_missing(
2178            "HelpAttrs",
2179            "HelpName",
2180            self.orig_loc,
2181            self.buf.as_ptr() as usize,
2182        ))
2183    }
2184}
2185impl HelpAttrs<'_> {
2186    pub fn new<'a>(buf: &'a [u8]) -> IterableHelpAttrs<'a> {
2187        IterableHelpAttrs::with_loc(buf, buf.as_ptr() as usize)
2188    }
2189    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2190        let res = match r#type {
2191            1u16 => "HelpName",
2192            _ => return None,
2193        };
2194        Some(res)
2195    }
2196}
2197#[derive(Clone, Copy, Default)]
2198pub struct IterableHelpAttrs<'a> {
2199    buf: &'a [u8],
2200    pos: usize,
2201    orig_loc: usize,
2202}
2203impl<'a> IterableHelpAttrs<'a> {
2204    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2205        Self {
2206            buf,
2207            pos: 0,
2208            orig_loc,
2209        }
2210    }
2211    pub fn get_buf(&self) -> &'a [u8] {
2212        self.buf
2213    }
2214}
2215impl<'a> Iterator for IterableHelpAttrs<'a> {
2216    type Item = Result<HelpAttrs<'a>, ErrorContext>;
2217    fn next(&mut self) -> Option<Self::Item> {
2218        let pos = self.pos;
2219        let mut r#type;
2220        loop {
2221            r#type = None;
2222            if self.buf.len() == self.pos {
2223                return None;
2224            }
2225            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2226                break;
2227            };
2228            r#type = Some(header.r#type);
2229            let res = match header.r#type {
2230                1u16 => HelpAttrs::HelpName({
2231                    let res = CStr::from_bytes_with_nul(next).ok();
2232                    let Some(val) = res else { break };
2233                    val
2234                }),
2235                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2236                n => continue,
2237            };
2238            return Some(Ok(res));
2239        }
2240        Some(Err(ErrorContext::new(
2241            "HelpAttrs",
2242            r#type.and_then(|t| HelpAttrs::attr_from_type(t)),
2243            self.orig_loc,
2244            self.buf.as_ptr().wrapping_add(pos) as usize,
2245        )))
2246    }
2247}
2248impl<'a> std::fmt::Debug for IterableHelpAttrs<'_> {
2249    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2250        let mut fmt = f.debug_struct("HelpAttrs");
2251        for attr in self.clone() {
2252            let attr = match attr {
2253                Ok(a) => a,
2254                Err(err) => {
2255                    fmt.finish()?;
2256                    f.write_str("Err(")?;
2257                    err.fmt(f)?;
2258                    return f.write_str(")");
2259                }
2260            };
2261            match attr {
2262                HelpAttrs::HelpName(val) => fmt.field("HelpName", &val),
2263            };
2264        }
2265        fmt.finish()
2266    }
2267}
2268impl IterableHelpAttrs<'_> {
2269    pub fn lookup_attr(
2270        &self,
2271        offset: usize,
2272        missing_type: Option<u16>,
2273    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2274        let mut stack = Vec::new();
2275        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2276        if cur == offset {
2277            stack.push(("HelpAttrs", offset));
2278            return (
2279                stack,
2280                missing_type.and_then(|t| HelpAttrs::attr_from_type(t)),
2281            );
2282        }
2283        if cur > offset || cur + self.buf.len() < offset {
2284            return (stack, None);
2285        }
2286        let mut attrs = self.clone();
2287        let mut last_off = cur + attrs.pos;
2288        while let Some(attr) = attrs.next() {
2289            let Ok(attr) = attr else { break };
2290            match attr {
2291                HelpAttrs::HelpName(val) => {
2292                    if last_off == offset {
2293                        stack.push(("HelpName", last_off));
2294                        break;
2295                    }
2296                }
2297                _ => {}
2298            };
2299            last_off = cur + attrs.pos;
2300        }
2301        if !stack.is_empty() {
2302            stack.push(("HelpAttrs", cur));
2303        }
2304        (stack, None)
2305    }
2306}
2307#[derive(Clone)]
2308pub enum NatProtoAttrs {
2309    NatPortMin(u16),
2310    NatPortMax(u16),
2311}
2312impl<'a> IterableNatProtoAttrs<'a> {
2313    pub fn get_nat_port_min(&self) -> Result<u16, ErrorContext> {
2314        let mut iter = self.clone();
2315        iter.pos = 0;
2316        for attr in iter {
2317            if let NatProtoAttrs::NatPortMin(val) = attr? {
2318                return Ok(val);
2319            }
2320        }
2321        Err(ErrorContext::new_missing(
2322            "NatProtoAttrs",
2323            "NatPortMin",
2324            self.orig_loc,
2325            self.buf.as_ptr() as usize,
2326        ))
2327    }
2328    pub fn get_nat_port_max(&self) -> Result<u16, ErrorContext> {
2329        let mut iter = self.clone();
2330        iter.pos = 0;
2331        for attr in iter {
2332            if let NatProtoAttrs::NatPortMax(val) = attr? {
2333                return Ok(val);
2334            }
2335        }
2336        Err(ErrorContext::new_missing(
2337            "NatProtoAttrs",
2338            "NatPortMax",
2339            self.orig_loc,
2340            self.buf.as_ptr() as usize,
2341        ))
2342    }
2343}
2344impl NatProtoAttrs {
2345    pub fn new<'a>(buf: &'a [u8]) -> IterableNatProtoAttrs<'a> {
2346        IterableNatProtoAttrs::with_loc(buf, buf.as_ptr() as usize)
2347    }
2348    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2349        let res = match r#type {
2350            1u16 => "NatPortMin",
2351            2u16 => "NatPortMax",
2352            _ => return None,
2353        };
2354        Some(res)
2355    }
2356}
2357#[derive(Clone, Copy, Default)]
2358pub struct IterableNatProtoAttrs<'a> {
2359    buf: &'a [u8],
2360    pos: usize,
2361    orig_loc: usize,
2362}
2363impl<'a> IterableNatProtoAttrs<'a> {
2364    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2365        Self {
2366            buf,
2367            pos: 0,
2368            orig_loc,
2369        }
2370    }
2371    pub fn get_buf(&self) -> &'a [u8] {
2372        self.buf
2373    }
2374}
2375impl<'a> Iterator for IterableNatProtoAttrs<'a> {
2376    type Item = Result<NatProtoAttrs, ErrorContext>;
2377    fn next(&mut self) -> Option<Self::Item> {
2378        let pos = self.pos;
2379        let mut r#type;
2380        loop {
2381            r#type = None;
2382            if self.buf.len() == self.pos {
2383                return None;
2384            }
2385            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2386                break;
2387            };
2388            r#type = Some(header.r#type);
2389            let res = match header.r#type {
2390                1u16 => NatProtoAttrs::NatPortMin({
2391                    let res = parse_be_u16(next);
2392                    let Some(val) = res else { break };
2393                    val
2394                }),
2395                2u16 => NatProtoAttrs::NatPortMax({
2396                    let res = parse_be_u16(next);
2397                    let Some(val) = res else { break };
2398                    val
2399                }),
2400                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2401                n => continue,
2402            };
2403            return Some(Ok(res));
2404        }
2405        Some(Err(ErrorContext::new(
2406            "NatProtoAttrs",
2407            r#type.and_then(|t| NatProtoAttrs::attr_from_type(t)),
2408            self.orig_loc,
2409            self.buf.as_ptr().wrapping_add(pos) as usize,
2410        )))
2411    }
2412}
2413impl std::fmt::Debug for IterableNatProtoAttrs<'_> {
2414    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2415        let mut fmt = f.debug_struct("NatProtoAttrs");
2416        for attr in self.clone() {
2417            let attr = match attr {
2418                Ok(a) => a,
2419                Err(err) => {
2420                    fmt.finish()?;
2421                    f.write_str("Err(")?;
2422                    err.fmt(f)?;
2423                    return f.write_str(")");
2424                }
2425            };
2426            match attr {
2427                NatProtoAttrs::NatPortMin(val) => fmt.field("NatPortMin", &val),
2428                NatProtoAttrs::NatPortMax(val) => fmt.field("NatPortMax", &val),
2429            };
2430        }
2431        fmt.finish()
2432    }
2433}
2434impl IterableNatProtoAttrs<'_> {
2435    pub fn lookup_attr(
2436        &self,
2437        offset: usize,
2438        missing_type: Option<u16>,
2439    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2440        let mut stack = Vec::new();
2441        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2442        if cur == offset {
2443            stack.push(("NatProtoAttrs", offset));
2444            return (
2445                stack,
2446                missing_type.and_then(|t| NatProtoAttrs::attr_from_type(t)),
2447            );
2448        }
2449        if cur > offset || cur + self.buf.len() < offset {
2450            return (stack, None);
2451        }
2452        let mut attrs = self.clone();
2453        let mut last_off = cur + attrs.pos;
2454        while let Some(attr) = attrs.next() {
2455            let Ok(attr) = attr else { break };
2456            match attr {
2457                NatProtoAttrs::NatPortMin(val) => {
2458                    if last_off == offset {
2459                        stack.push(("NatPortMin", last_off));
2460                        break;
2461                    }
2462                }
2463                NatProtoAttrs::NatPortMax(val) => {
2464                    if last_off == offset {
2465                        stack.push(("NatPortMax", last_off));
2466                        break;
2467                    }
2468                }
2469                _ => {}
2470            };
2471            last_off = cur + attrs.pos;
2472        }
2473        if !stack.is_empty() {
2474            stack.push(("NatProtoAttrs", cur));
2475        }
2476        (stack, None)
2477    }
2478}
2479#[derive(Clone)]
2480pub enum NatAttrs<'a> {
2481    NatV4Minip(u32),
2482    NatV4Maxip(u32),
2483    NatV6Minip(&'a [u8]),
2484    NatV6Maxip(&'a [u8]),
2485    NatProto(IterableNatProtoAttrs<'a>),
2486}
2487impl<'a> IterableNatAttrs<'a> {
2488    pub fn get_nat_v4_minip(&self) -> Result<u32, ErrorContext> {
2489        let mut iter = self.clone();
2490        iter.pos = 0;
2491        for attr in iter {
2492            if let NatAttrs::NatV4Minip(val) = attr? {
2493                return Ok(val);
2494            }
2495        }
2496        Err(ErrorContext::new_missing(
2497            "NatAttrs",
2498            "NatV4Minip",
2499            self.orig_loc,
2500            self.buf.as_ptr() as usize,
2501        ))
2502    }
2503    pub fn get_nat_v4_maxip(&self) -> Result<u32, ErrorContext> {
2504        let mut iter = self.clone();
2505        iter.pos = 0;
2506        for attr in iter {
2507            if let NatAttrs::NatV4Maxip(val) = attr? {
2508                return Ok(val);
2509            }
2510        }
2511        Err(ErrorContext::new_missing(
2512            "NatAttrs",
2513            "NatV4Maxip",
2514            self.orig_loc,
2515            self.buf.as_ptr() as usize,
2516        ))
2517    }
2518    pub fn get_nat_v6_minip(&self) -> Result<&'a [u8], ErrorContext> {
2519        let mut iter = self.clone();
2520        iter.pos = 0;
2521        for attr in iter {
2522            if let NatAttrs::NatV6Minip(val) = attr? {
2523                return Ok(val);
2524            }
2525        }
2526        Err(ErrorContext::new_missing(
2527            "NatAttrs",
2528            "NatV6Minip",
2529            self.orig_loc,
2530            self.buf.as_ptr() as usize,
2531        ))
2532    }
2533    pub fn get_nat_v6_maxip(&self) -> Result<&'a [u8], ErrorContext> {
2534        let mut iter = self.clone();
2535        iter.pos = 0;
2536        for attr in iter {
2537            if let NatAttrs::NatV6Maxip(val) = attr? {
2538                return Ok(val);
2539            }
2540        }
2541        Err(ErrorContext::new_missing(
2542            "NatAttrs",
2543            "NatV6Maxip",
2544            self.orig_loc,
2545            self.buf.as_ptr() as usize,
2546        ))
2547    }
2548    pub fn get_nat_proto(&self) -> Result<IterableNatProtoAttrs<'a>, ErrorContext> {
2549        let mut iter = self.clone();
2550        iter.pos = 0;
2551        for attr in iter {
2552            if let NatAttrs::NatProto(val) = attr? {
2553                return Ok(val);
2554            }
2555        }
2556        Err(ErrorContext::new_missing(
2557            "NatAttrs",
2558            "NatProto",
2559            self.orig_loc,
2560            self.buf.as_ptr() as usize,
2561        ))
2562    }
2563}
2564impl NatAttrs<'_> {
2565    pub fn new<'a>(buf: &'a [u8]) -> IterableNatAttrs<'a> {
2566        IterableNatAttrs::with_loc(buf, buf.as_ptr() as usize)
2567    }
2568    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2569        let res = match r#type {
2570            1u16 => "NatV4Minip",
2571            2u16 => "NatV4Maxip",
2572            3u16 => "NatV6Minip",
2573            4u16 => "NatV6Maxip",
2574            5u16 => "NatProto",
2575            _ => return None,
2576        };
2577        Some(res)
2578    }
2579}
2580#[derive(Clone, Copy, Default)]
2581pub struct IterableNatAttrs<'a> {
2582    buf: &'a [u8],
2583    pos: usize,
2584    orig_loc: usize,
2585}
2586impl<'a> IterableNatAttrs<'a> {
2587    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2588        Self {
2589            buf,
2590            pos: 0,
2591            orig_loc,
2592        }
2593    }
2594    pub fn get_buf(&self) -> &'a [u8] {
2595        self.buf
2596    }
2597}
2598impl<'a> Iterator for IterableNatAttrs<'a> {
2599    type Item = Result<NatAttrs<'a>, ErrorContext>;
2600    fn next(&mut self) -> Option<Self::Item> {
2601        let pos = self.pos;
2602        let mut r#type;
2603        loop {
2604            r#type = None;
2605            if self.buf.len() == self.pos {
2606                return None;
2607            }
2608            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2609                break;
2610            };
2611            r#type = Some(header.r#type);
2612            let res = match header.r#type {
2613                1u16 => NatAttrs::NatV4Minip({
2614                    let res = parse_be_u32(next);
2615                    let Some(val) = res else { break };
2616                    val
2617                }),
2618                2u16 => NatAttrs::NatV4Maxip({
2619                    let res = parse_be_u32(next);
2620                    let Some(val) = res else { break };
2621                    val
2622                }),
2623                3u16 => NatAttrs::NatV6Minip({
2624                    let res = Some(next);
2625                    let Some(val) = res else { break };
2626                    val
2627                }),
2628                4u16 => NatAttrs::NatV6Maxip({
2629                    let res = Some(next);
2630                    let Some(val) = res else { break };
2631                    val
2632                }),
2633                5u16 => NatAttrs::NatProto({
2634                    let res = Some(IterableNatProtoAttrs::with_loc(next, self.orig_loc));
2635                    let Some(val) = res else { break };
2636                    val
2637                }),
2638                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2639                n => continue,
2640            };
2641            return Some(Ok(res));
2642        }
2643        Some(Err(ErrorContext::new(
2644            "NatAttrs",
2645            r#type.and_then(|t| NatAttrs::attr_from_type(t)),
2646            self.orig_loc,
2647            self.buf.as_ptr().wrapping_add(pos) as usize,
2648        )))
2649    }
2650}
2651impl<'a> std::fmt::Debug for IterableNatAttrs<'_> {
2652    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2653        let mut fmt = f.debug_struct("NatAttrs");
2654        for attr in self.clone() {
2655            let attr = match attr {
2656                Ok(a) => a,
2657                Err(err) => {
2658                    fmt.finish()?;
2659                    f.write_str("Err(")?;
2660                    err.fmt(f)?;
2661                    return f.write_str(")");
2662                }
2663            };
2664            match attr {
2665                NatAttrs::NatV4Minip(val) => fmt.field("NatV4Minip", &val),
2666                NatAttrs::NatV4Maxip(val) => fmt.field("NatV4Maxip", &val),
2667                NatAttrs::NatV6Minip(val) => fmt.field("NatV6Minip", &val),
2668                NatAttrs::NatV6Maxip(val) => fmt.field("NatV6Maxip", &val),
2669                NatAttrs::NatProto(val) => fmt.field("NatProto", &val),
2670            };
2671        }
2672        fmt.finish()
2673    }
2674}
2675impl IterableNatAttrs<'_> {
2676    pub fn lookup_attr(
2677        &self,
2678        offset: usize,
2679        missing_type: Option<u16>,
2680    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2681        let mut stack = Vec::new();
2682        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2683        if cur == offset {
2684            stack.push(("NatAttrs", offset));
2685            return (
2686                stack,
2687                missing_type.and_then(|t| NatAttrs::attr_from_type(t)),
2688            );
2689        }
2690        if cur > offset || cur + self.buf.len() < offset {
2691            return (stack, None);
2692        }
2693        let mut attrs = self.clone();
2694        let mut last_off = cur + attrs.pos;
2695        let mut missing = None;
2696        while let Some(attr) = attrs.next() {
2697            let Ok(attr) = attr else { break };
2698            match attr {
2699                NatAttrs::NatV4Minip(val) => {
2700                    if last_off == offset {
2701                        stack.push(("NatV4Minip", last_off));
2702                        break;
2703                    }
2704                }
2705                NatAttrs::NatV4Maxip(val) => {
2706                    if last_off == offset {
2707                        stack.push(("NatV4Maxip", last_off));
2708                        break;
2709                    }
2710                }
2711                NatAttrs::NatV6Minip(val) => {
2712                    if last_off == offset {
2713                        stack.push(("NatV6Minip", last_off));
2714                        break;
2715                    }
2716                }
2717                NatAttrs::NatV6Maxip(val) => {
2718                    if last_off == offset {
2719                        stack.push(("NatV6Maxip", last_off));
2720                        break;
2721                    }
2722                }
2723                NatAttrs::NatProto(val) => {
2724                    (stack, missing) = val.lookup_attr(offset, missing_type);
2725                    if !stack.is_empty() {
2726                        break;
2727                    }
2728                }
2729                _ => {}
2730            };
2731            last_off = cur + attrs.pos;
2732        }
2733        if !stack.is_empty() {
2734            stack.push(("NatAttrs", cur));
2735        }
2736        (stack, missing)
2737    }
2738}
2739#[derive(Clone)]
2740pub enum SeqadjAttrs {
2741    CorrectionPos(u32),
2742    OffsetBefore(u32),
2743    OffsetAfter(u32),
2744}
2745impl<'a> IterableSeqadjAttrs<'a> {
2746    pub fn get_correction_pos(&self) -> Result<u32, ErrorContext> {
2747        let mut iter = self.clone();
2748        iter.pos = 0;
2749        for attr in iter {
2750            if let SeqadjAttrs::CorrectionPos(val) = attr? {
2751                return Ok(val);
2752            }
2753        }
2754        Err(ErrorContext::new_missing(
2755            "SeqadjAttrs",
2756            "CorrectionPos",
2757            self.orig_loc,
2758            self.buf.as_ptr() as usize,
2759        ))
2760    }
2761    pub fn get_offset_before(&self) -> Result<u32, ErrorContext> {
2762        let mut iter = self.clone();
2763        iter.pos = 0;
2764        for attr in iter {
2765            if let SeqadjAttrs::OffsetBefore(val) = attr? {
2766                return Ok(val);
2767            }
2768        }
2769        Err(ErrorContext::new_missing(
2770            "SeqadjAttrs",
2771            "OffsetBefore",
2772            self.orig_loc,
2773            self.buf.as_ptr() as usize,
2774        ))
2775    }
2776    pub fn get_offset_after(&self) -> Result<u32, ErrorContext> {
2777        let mut iter = self.clone();
2778        iter.pos = 0;
2779        for attr in iter {
2780            if let SeqadjAttrs::OffsetAfter(val) = attr? {
2781                return Ok(val);
2782            }
2783        }
2784        Err(ErrorContext::new_missing(
2785            "SeqadjAttrs",
2786            "OffsetAfter",
2787            self.orig_loc,
2788            self.buf.as_ptr() as usize,
2789        ))
2790    }
2791}
2792impl SeqadjAttrs {
2793    pub fn new<'a>(buf: &'a [u8]) -> IterableSeqadjAttrs<'a> {
2794        IterableSeqadjAttrs::with_loc(buf, buf.as_ptr() as usize)
2795    }
2796    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2797        let res = match r#type {
2798            1u16 => "CorrectionPos",
2799            2u16 => "OffsetBefore",
2800            3u16 => "OffsetAfter",
2801            _ => return None,
2802        };
2803        Some(res)
2804    }
2805}
2806#[derive(Clone, Copy, Default)]
2807pub struct IterableSeqadjAttrs<'a> {
2808    buf: &'a [u8],
2809    pos: usize,
2810    orig_loc: usize,
2811}
2812impl<'a> IterableSeqadjAttrs<'a> {
2813    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2814        Self {
2815            buf,
2816            pos: 0,
2817            orig_loc,
2818        }
2819    }
2820    pub fn get_buf(&self) -> &'a [u8] {
2821        self.buf
2822    }
2823}
2824impl<'a> Iterator for IterableSeqadjAttrs<'a> {
2825    type Item = Result<SeqadjAttrs, ErrorContext>;
2826    fn next(&mut self) -> Option<Self::Item> {
2827        let pos = self.pos;
2828        let mut r#type;
2829        loop {
2830            r#type = None;
2831            if self.buf.len() == self.pos {
2832                return None;
2833            }
2834            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2835                break;
2836            };
2837            r#type = Some(header.r#type);
2838            let res = match header.r#type {
2839                1u16 => SeqadjAttrs::CorrectionPos({
2840                    let res = parse_be_u32(next);
2841                    let Some(val) = res else { break };
2842                    val
2843                }),
2844                2u16 => SeqadjAttrs::OffsetBefore({
2845                    let res = parse_be_u32(next);
2846                    let Some(val) = res else { break };
2847                    val
2848                }),
2849                3u16 => SeqadjAttrs::OffsetAfter({
2850                    let res = parse_be_u32(next);
2851                    let Some(val) = res else { break };
2852                    val
2853                }),
2854                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2855                n => continue,
2856            };
2857            return Some(Ok(res));
2858        }
2859        Some(Err(ErrorContext::new(
2860            "SeqadjAttrs",
2861            r#type.and_then(|t| SeqadjAttrs::attr_from_type(t)),
2862            self.orig_loc,
2863            self.buf.as_ptr().wrapping_add(pos) as usize,
2864        )))
2865    }
2866}
2867impl std::fmt::Debug for IterableSeqadjAttrs<'_> {
2868    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2869        let mut fmt = f.debug_struct("SeqadjAttrs");
2870        for attr in self.clone() {
2871            let attr = match attr {
2872                Ok(a) => a,
2873                Err(err) => {
2874                    fmt.finish()?;
2875                    f.write_str("Err(")?;
2876                    err.fmt(f)?;
2877                    return f.write_str(")");
2878                }
2879            };
2880            match attr {
2881                SeqadjAttrs::CorrectionPos(val) => fmt.field("CorrectionPos", &val),
2882                SeqadjAttrs::OffsetBefore(val) => fmt.field("OffsetBefore", &val),
2883                SeqadjAttrs::OffsetAfter(val) => fmt.field("OffsetAfter", &val),
2884            };
2885        }
2886        fmt.finish()
2887    }
2888}
2889impl IterableSeqadjAttrs<'_> {
2890    pub fn lookup_attr(
2891        &self,
2892        offset: usize,
2893        missing_type: Option<u16>,
2894    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2895        let mut stack = Vec::new();
2896        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2897        if cur == offset {
2898            stack.push(("SeqadjAttrs", offset));
2899            return (
2900                stack,
2901                missing_type.and_then(|t| SeqadjAttrs::attr_from_type(t)),
2902            );
2903        }
2904        if cur > offset || cur + self.buf.len() < offset {
2905            return (stack, None);
2906        }
2907        let mut attrs = self.clone();
2908        let mut last_off = cur + attrs.pos;
2909        while let Some(attr) = attrs.next() {
2910            let Ok(attr) = attr else { break };
2911            match attr {
2912                SeqadjAttrs::CorrectionPos(val) => {
2913                    if last_off == offset {
2914                        stack.push(("CorrectionPos", last_off));
2915                        break;
2916                    }
2917                }
2918                SeqadjAttrs::OffsetBefore(val) => {
2919                    if last_off == offset {
2920                        stack.push(("OffsetBefore", last_off));
2921                        break;
2922                    }
2923                }
2924                SeqadjAttrs::OffsetAfter(val) => {
2925                    if last_off == offset {
2926                        stack.push(("OffsetAfter", last_off));
2927                        break;
2928                    }
2929                }
2930                _ => {}
2931            };
2932            last_off = cur + attrs.pos;
2933        }
2934        if !stack.is_empty() {
2935            stack.push(("SeqadjAttrs", cur));
2936        }
2937        (stack, None)
2938    }
2939}
2940#[derive(Clone)]
2941pub enum SecctxAttrs<'a> {
2942    SecctxName(&'a CStr),
2943}
2944impl<'a> IterableSecctxAttrs<'a> {
2945    pub fn get_secctx_name(&self) -> Result<&'a CStr, ErrorContext> {
2946        let mut iter = self.clone();
2947        iter.pos = 0;
2948        for attr in iter {
2949            if let SecctxAttrs::SecctxName(val) = attr? {
2950                return Ok(val);
2951            }
2952        }
2953        Err(ErrorContext::new_missing(
2954            "SecctxAttrs",
2955            "SecctxName",
2956            self.orig_loc,
2957            self.buf.as_ptr() as usize,
2958        ))
2959    }
2960}
2961impl SecctxAttrs<'_> {
2962    pub fn new<'a>(buf: &'a [u8]) -> IterableSecctxAttrs<'a> {
2963        IterableSecctxAttrs::with_loc(buf, buf.as_ptr() as usize)
2964    }
2965    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2966        let res = match r#type {
2967            1u16 => "SecctxName",
2968            _ => return None,
2969        };
2970        Some(res)
2971    }
2972}
2973#[derive(Clone, Copy, Default)]
2974pub struct IterableSecctxAttrs<'a> {
2975    buf: &'a [u8],
2976    pos: usize,
2977    orig_loc: usize,
2978}
2979impl<'a> IterableSecctxAttrs<'a> {
2980    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2981        Self {
2982            buf,
2983            pos: 0,
2984            orig_loc,
2985        }
2986    }
2987    pub fn get_buf(&self) -> &'a [u8] {
2988        self.buf
2989    }
2990}
2991impl<'a> Iterator for IterableSecctxAttrs<'a> {
2992    type Item = Result<SecctxAttrs<'a>, ErrorContext>;
2993    fn next(&mut self) -> Option<Self::Item> {
2994        let pos = self.pos;
2995        let mut r#type;
2996        loop {
2997            r#type = None;
2998            if self.buf.len() == self.pos {
2999                return None;
3000            }
3001            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3002                break;
3003            };
3004            r#type = Some(header.r#type);
3005            let res = match header.r#type {
3006                1u16 => SecctxAttrs::SecctxName({
3007                    let res = CStr::from_bytes_with_nul(next).ok();
3008                    let Some(val) = res else { break };
3009                    val
3010                }),
3011                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3012                n => continue,
3013            };
3014            return Some(Ok(res));
3015        }
3016        Some(Err(ErrorContext::new(
3017            "SecctxAttrs",
3018            r#type.and_then(|t| SecctxAttrs::attr_from_type(t)),
3019            self.orig_loc,
3020            self.buf.as_ptr().wrapping_add(pos) as usize,
3021        )))
3022    }
3023}
3024impl<'a> std::fmt::Debug for IterableSecctxAttrs<'_> {
3025    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3026        let mut fmt = f.debug_struct("SecctxAttrs");
3027        for attr in self.clone() {
3028            let attr = match attr {
3029                Ok(a) => a,
3030                Err(err) => {
3031                    fmt.finish()?;
3032                    f.write_str("Err(")?;
3033                    err.fmt(f)?;
3034                    return f.write_str(")");
3035                }
3036            };
3037            match attr {
3038                SecctxAttrs::SecctxName(val) => fmt.field("SecctxName", &val),
3039            };
3040        }
3041        fmt.finish()
3042    }
3043}
3044impl IterableSecctxAttrs<'_> {
3045    pub fn lookup_attr(
3046        &self,
3047        offset: usize,
3048        missing_type: Option<u16>,
3049    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3050        let mut stack = Vec::new();
3051        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3052        if cur == offset {
3053            stack.push(("SecctxAttrs", offset));
3054            return (
3055                stack,
3056                missing_type.and_then(|t| SecctxAttrs::attr_from_type(t)),
3057            );
3058        }
3059        if cur > offset || cur + self.buf.len() < offset {
3060            return (stack, None);
3061        }
3062        let mut attrs = self.clone();
3063        let mut last_off = cur + attrs.pos;
3064        while let Some(attr) = attrs.next() {
3065            let Ok(attr) = attr else { break };
3066            match attr {
3067                SecctxAttrs::SecctxName(val) => {
3068                    if last_off == offset {
3069                        stack.push(("SecctxName", last_off));
3070                        break;
3071                    }
3072                }
3073                _ => {}
3074            };
3075            last_off = cur + attrs.pos;
3076        }
3077        if !stack.is_empty() {
3078            stack.push(("SecctxAttrs", cur));
3079        }
3080        (stack, None)
3081    }
3082}
3083#[derive(Clone)]
3084pub enum SynproxyAttrs {
3085    Isn(u32),
3086    Its(u32),
3087    Tsoff(u32),
3088}
3089impl<'a> IterableSynproxyAttrs<'a> {
3090    pub fn get_isn(&self) -> Result<u32, ErrorContext> {
3091        let mut iter = self.clone();
3092        iter.pos = 0;
3093        for attr in iter {
3094            if let SynproxyAttrs::Isn(val) = attr? {
3095                return Ok(val);
3096            }
3097        }
3098        Err(ErrorContext::new_missing(
3099            "SynproxyAttrs",
3100            "Isn",
3101            self.orig_loc,
3102            self.buf.as_ptr() as usize,
3103        ))
3104    }
3105    pub fn get_its(&self) -> Result<u32, ErrorContext> {
3106        let mut iter = self.clone();
3107        iter.pos = 0;
3108        for attr in iter {
3109            if let SynproxyAttrs::Its(val) = attr? {
3110                return Ok(val);
3111            }
3112        }
3113        Err(ErrorContext::new_missing(
3114            "SynproxyAttrs",
3115            "Its",
3116            self.orig_loc,
3117            self.buf.as_ptr() as usize,
3118        ))
3119    }
3120    pub fn get_tsoff(&self) -> Result<u32, ErrorContext> {
3121        let mut iter = self.clone();
3122        iter.pos = 0;
3123        for attr in iter {
3124            if let SynproxyAttrs::Tsoff(val) = attr? {
3125                return Ok(val);
3126            }
3127        }
3128        Err(ErrorContext::new_missing(
3129            "SynproxyAttrs",
3130            "Tsoff",
3131            self.orig_loc,
3132            self.buf.as_ptr() as usize,
3133        ))
3134    }
3135}
3136impl SynproxyAttrs {
3137    pub fn new<'a>(buf: &'a [u8]) -> IterableSynproxyAttrs<'a> {
3138        IterableSynproxyAttrs::with_loc(buf, buf.as_ptr() as usize)
3139    }
3140    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3141        let res = match r#type {
3142            1u16 => "Isn",
3143            2u16 => "Its",
3144            3u16 => "Tsoff",
3145            _ => return None,
3146        };
3147        Some(res)
3148    }
3149}
3150#[derive(Clone, Copy, Default)]
3151pub struct IterableSynproxyAttrs<'a> {
3152    buf: &'a [u8],
3153    pos: usize,
3154    orig_loc: usize,
3155}
3156impl<'a> IterableSynproxyAttrs<'a> {
3157    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3158        Self {
3159            buf,
3160            pos: 0,
3161            orig_loc,
3162        }
3163    }
3164    pub fn get_buf(&self) -> &'a [u8] {
3165        self.buf
3166    }
3167}
3168impl<'a> Iterator for IterableSynproxyAttrs<'a> {
3169    type Item = Result<SynproxyAttrs, ErrorContext>;
3170    fn next(&mut self) -> Option<Self::Item> {
3171        let pos = self.pos;
3172        let mut r#type;
3173        loop {
3174            r#type = None;
3175            if self.buf.len() == self.pos {
3176                return None;
3177            }
3178            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3179                break;
3180            };
3181            r#type = Some(header.r#type);
3182            let res = match header.r#type {
3183                1u16 => SynproxyAttrs::Isn({
3184                    let res = parse_be_u32(next);
3185                    let Some(val) = res else { break };
3186                    val
3187                }),
3188                2u16 => SynproxyAttrs::Its({
3189                    let res = parse_be_u32(next);
3190                    let Some(val) = res else { break };
3191                    val
3192                }),
3193                3u16 => SynproxyAttrs::Tsoff({
3194                    let res = parse_be_u32(next);
3195                    let Some(val) = res else { break };
3196                    val
3197                }),
3198                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3199                n => continue,
3200            };
3201            return Some(Ok(res));
3202        }
3203        Some(Err(ErrorContext::new(
3204            "SynproxyAttrs",
3205            r#type.and_then(|t| SynproxyAttrs::attr_from_type(t)),
3206            self.orig_loc,
3207            self.buf.as_ptr().wrapping_add(pos) as usize,
3208        )))
3209    }
3210}
3211impl std::fmt::Debug for IterableSynproxyAttrs<'_> {
3212    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3213        let mut fmt = f.debug_struct("SynproxyAttrs");
3214        for attr in self.clone() {
3215            let attr = match attr {
3216                Ok(a) => a,
3217                Err(err) => {
3218                    fmt.finish()?;
3219                    f.write_str("Err(")?;
3220                    err.fmt(f)?;
3221                    return f.write_str(")");
3222                }
3223            };
3224            match attr {
3225                SynproxyAttrs::Isn(val) => fmt.field("Isn", &val),
3226                SynproxyAttrs::Its(val) => fmt.field("Its", &val),
3227                SynproxyAttrs::Tsoff(val) => fmt.field("Tsoff", &val),
3228            };
3229        }
3230        fmt.finish()
3231    }
3232}
3233impl IterableSynproxyAttrs<'_> {
3234    pub fn lookup_attr(
3235        &self,
3236        offset: usize,
3237        missing_type: Option<u16>,
3238    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3239        let mut stack = Vec::new();
3240        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3241        if cur == offset {
3242            stack.push(("SynproxyAttrs", offset));
3243            return (
3244                stack,
3245                missing_type.and_then(|t| SynproxyAttrs::attr_from_type(t)),
3246            );
3247        }
3248        if cur > offset || cur + self.buf.len() < offset {
3249            return (stack, None);
3250        }
3251        let mut attrs = self.clone();
3252        let mut last_off = cur + attrs.pos;
3253        while let Some(attr) = attrs.next() {
3254            let Ok(attr) = attr else { break };
3255            match attr {
3256                SynproxyAttrs::Isn(val) => {
3257                    if last_off == offset {
3258                        stack.push(("Isn", last_off));
3259                        break;
3260                    }
3261                }
3262                SynproxyAttrs::Its(val) => {
3263                    if last_off == offset {
3264                        stack.push(("Its", last_off));
3265                        break;
3266                    }
3267                }
3268                SynproxyAttrs::Tsoff(val) => {
3269                    if last_off == offset {
3270                        stack.push(("Tsoff", last_off));
3271                        break;
3272                    }
3273                }
3274                _ => {}
3275            };
3276            last_off = cur + attrs.pos;
3277        }
3278        if !stack.is_empty() {
3279            stack.push(("SynproxyAttrs", cur));
3280        }
3281        (stack, None)
3282    }
3283}
3284#[derive(Clone)]
3285pub enum ConntrackAttrs<'a> {
3286    #[doc = "conntrack l3+l4 protocol information, original direction"]
3287    TupleOrig(IterableTupleAttrs<'a>),
3288    #[doc = "conntrack l3+l4 protocol information, reply direction"]
3289    TupleReply(IterableTupleAttrs<'a>),
3290    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
3291    Status(u32),
3292    Protoinfo(IterableProtoinfoAttrs<'a>),
3293    Help(IterableHelpAttrs<'a>),
3294    NatSrc(IterableNatAttrs<'a>),
3295    Timeout(u32),
3296    Mark(u32),
3297    CountersOrig(IterableCounterAttrs<'a>),
3298    CountersReply(IterableCounterAttrs<'a>),
3299    Use(u32),
3300    Id(u32),
3301    NatDst(IterableNatAttrs<'a>),
3302    TupleMaster(IterableTupleAttrs<'a>),
3303    SeqAdjOrig(IterableSeqadjAttrs<'a>),
3304    SeqAdjReply(IterableSeqadjAttrs<'a>),
3305    #[doc = "obsolete"]
3306    Secmark(&'a [u8]),
3307    #[doc = "conntrack zone id"]
3308    Zone(u16),
3309    Secctx(IterableSecctxAttrs<'a>),
3310    Timestamp(u64),
3311    MarkMask(u32),
3312    Labels(&'a [u8]),
3313    LabelsMask(&'a [u8]),
3314    Synproxy(IterableSynproxyAttrs<'a>),
3315    Filter(IterableTupleAttrs<'a>),
3316    #[doc = "conntrack flag bits to change\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
3317    StatusMask(u32),
3318    TimestampEvent(u64),
3319}
3320impl<'a> IterableConntrackAttrs<'a> {
3321    #[doc = "conntrack l3+l4 protocol information, original direction"]
3322    pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3323        let mut iter = self.clone();
3324        iter.pos = 0;
3325        for attr in iter {
3326            if let ConntrackAttrs::TupleOrig(val) = attr? {
3327                return Ok(val);
3328            }
3329        }
3330        Err(ErrorContext::new_missing(
3331            "ConntrackAttrs",
3332            "TupleOrig",
3333            self.orig_loc,
3334            self.buf.as_ptr() as usize,
3335        ))
3336    }
3337    #[doc = "conntrack l3+l4 protocol information, reply direction"]
3338    pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3339        let mut iter = self.clone();
3340        iter.pos = 0;
3341        for attr in iter {
3342            if let ConntrackAttrs::TupleReply(val) = attr? {
3343                return Ok(val);
3344            }
3345        }
3346        Err(ErrorContext::new_missing(
3347            "ConntrackAttrs",
3348            "TupleReply",
3349            self.orig_loc,
3350            self.buf.as_ptr() as usize,
3351        ))
3352    }
3353    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
3354    pub fn get_status(&self) -> Result<u32, ErrorContext> {
3355        let mut iter = self.clone();
3356        iter.pos = 0;
3357        for attr in iter {
3358            if let ConntrackAttrs::Status(val) = attr? {
3359                return Ok(val);
3360            }
3361        }
3362        Err(ErrorContext::new_missing(
3363            "ConntrackAttrs",
3364            "Status",
3365            self.orig_loc,
3366            self.buf.as_ptr() as usize,
3367        ))
3368    }
3369    pub fn get_protoinfo(&self) -> Result<IterableProtoinfoAttrs<'a>, ErrorContext> {
3370        let mut iter = self.clone();
3371        iter.pos = 0;
3372        for attr in iter {
3373            if let ConntrackAttrs::Protoinfo(val) = attr? {
3374                return Ok(val);
3375            }
3376        }
3377        Err(ErrorContext::new_missing(
3378            "ConntrackAttrs",
3379            "Protoinfo",
3380            self.orig_loc,
3381            self.buf.as_ptr() as usize,
3382        ))
3383    }
3384    pub fn get_help(&self) -> Result<IterableHelpAttrs<'a>, ErrorContext> {
3385        let mut iter = self.clone();
3386        iter.pos = 0;
3387        for attr in iter {
3388            if let ConntrackAttrs::Help(val) = attr? {
3389                return Ok(val);
3390            }
3391        }
3392        Err(ErrorContext::new_missing(
3393            "ConntrackAttrs",
3394            "Help",
3395            self.orig_loc,
3396            self.buf.as_ptr() as usize,
3397        ))
3398    }
3399    pub fn get_nat_src(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
3400        let mut iter = self.clone();
3401        iter.pos = 0;
3402        for attr in iter {
3403            if let ConntrackAttrs::NatSrc(val) = attr? {
3404                return Ok(val);
3405            }
3406        }
3407        Err(ErrorContext::new_missing(
3408            "ConntrackAttrs",
3409            "NatSrc",
3410            self.orig_loc,
3411            self.buf.as_ptr() as usize,
3412        ))
3413    }
3414    pub fn get_timeout(&self) -> Result<u32, ErrorContext> {
3415        let mut iter = self.clone();
3416        iter.pos = 0;
3417        for attr in iter {
3418            if let ConntrackAttrs::Timeout(val) = attr? {
3419                return Ok(val);
3420            }
3421        }
3422        Err(ErrorContext::new_missing(
3423            "ConntrackAttrs",
3424            "Timeout",
3425            self.orig_loc,
3426            self.buf.as_ptr() as usize,
3427        ))
3428    }
3429    pub fn get_mark(&self) -> Result<u32, ErrorContext> {
3430        let mut iter = self.clone();
3431        iter.pos = 0;
3432        for attr in iter {
3433            if let ConntrackAttrs::Mark(val) = attr? {
3434                return Ok(val);
3435            }
3436        }
3437        Err(ErrorContext::new_missing(
3438            "ConntrackAttrs",
3439            "Mark",
3440            self.orig_loc,
3441            self.buf.as_ptr() as usize,
3442        ))
3443    }
3444    pub fn get_counters_orig(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
3445        let mut iter = self.clone();
3446        iter.pos = 0;
3447        for attr in iter {
3448            if let ConntrackAttrs::CountersOrig(val) = attr? {
3449                return Ok(val);
3450            }
3451        }
3452        Err(ErrorContext::new_missing(
3453            "ConntrackAttrs",
3454            "CountersOrig",
3455            self.orig_loc,
3456            self.buf.as_ptr() as usize,
3457        ))
3458    }
3459    pub fn get_counters_reply(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
3460        let mut iter = self.clone();
3461        iter.pos = 0;
3462        for attr in iter {
3463            if let ConntrackAttrs::CountersReply(val) = attr? {
3464                return Ok(val);
3465            }
3466        }
3467        Err(ErrorContext::new_missing(
3468            "ConntrackAttrs",
3469            "CountersReply",
3470            self.orig_loc,
3471            self.buf.as_ptr() as usize,
3472        ))
3473    }
3474    pub fn get_use(&self) -> Result<u32, ErrorContext> {
3475        let mut iter = self.clone();
3476        iter.pos = 0;
3477        for attr in iter {
3478            if let ConntrackAttrs::Use(val) = attr? {
3479                return Ok(val);
3480            }
3481        }
3482        Err(ErrorContext::new_missing(
3483            "ConntrackAttrs",
3484            "Use",
3485            self.orig_loc,
3486            self.buf.as_ptr() as usize,
3487        ))
3488    }
3489    pub fn get_id(&self) -> Result<u32, ErrorContext> {
3490        let mut iter = self.clone();
3491        iter.pos = 0;
3492        for attr in iter {
3493            if let ConntrackAttrs::Id(val) = attr? {
3494                return Ok(val);
3495            }
3496        }
3497        Err(ErrorContext::new_missing(
3498            "ConntrackAttrs",
3499            "Id",
3500            self.orig_loc,
3501            self.buf.as_ptr() as usize,
3502        ))
3503    }
3504    pub fn get_nat_dst(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
3505        let mut iter = self.clone();
3506        iter.pos = 0;
3507        for attr in iter {
3508            if let ConntrackAttrs::NatDst(val) = attr? {
3509                return Ok(val);
3510            }
3511        }
3512        Err(ErrorContext::new_missing(
3513            "ConntrackAttrs",
3514            "NatDst",
3515            self.orig_loc,
3516            self.buf.as_ptr() as usize,
3517        ))
3518    }
3519    pub fn get_tuple_master(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3520        let mut iter = self.clone();
3521        iter.pos = 0;
3522        for attr in iter {
3523            if let ConntrackAttrs::TupleMaster(val) = attr? {
3524                return Ok(val);
3525            }
3526        }
3527        Err(ErrorContext::new_missing(
3528            "ConntrackAttrs",
3529            "TupleMaster",
3530            self.orig_loc,
3531            self.buf.as_ptr() as usize,
3532        ))
3533    }
3534    pub fn get_seq_adj_orig(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
3535        let mut iter = self.clone();
3536        iter.pos = 0;
3537        for attr in iter {
3538            if let ConntrackAttrs::SeqAdjOrig(val) = attr? {
3539                return Ok(val);
3540            }
3541        }
3542        Err(ErrorContext::new_missing(
3543            "ConntrackAttrs",
3544            "SeqAdjOrig",
3545            self.orig_loc,
3546            self.buf.as_ptr() as usize,
3547        ))
3548    }
3549    pub fn get_seq_adj_reply(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
3550        let mut iter = self.clone();
3551        iter.pos = 0;
3552        for attr in iter {
3553            if let ConntrackAttrs::SeqAdjReply(val) = attr? {
3554                return Ok(val);
3555            }
3556        }
3557        Err(ErrorContext::new_missing(
3558            "ConntrackAttrs",
3559            "SeqAdjReply",
3560            self.orig_loc,
3561            self.buf.as_ptr() as usize,
3562        ))
3563    }
3564    #[doc = "obsolete"]
3565    pub fn get_secmark(&self) -> Result<&'a [u8], ErrorContext> {
3566        let mut iter = self.clone();
3567        iter.pos = 0;
3568        for attr in iter {
3569            if let ConntrackAttrs::Secmark(val) = attr? {
3570                return Ok(val);
3571            }
3572        }
3573        Err(ErrorContext::new_missing(
3574            "ConntrackAttrs",
3575            "Secmark",
3576            self.orig_loc,
3577            self.buf.as_ptr() as usize,
3578        ))
3579    }
3580    #[doc = "conntrack zone id"]
3581    pub fn get_zone(&self) -> Result<u16, ErrorContext> {
3582        let mut iter = self.clone();
3583        iter.pos = 0;
3584        for attr in iter {
3585            if let ConntrackAttrs::Zone(val) = attr? {
3586                return Ok(val);
3587            }
3588        }
3589        Err(ErrorContext::new_missing(
3590            "ConntrackAttrs",
3591            "Zone",
3592            self.orig_loc,
3593            self.buf.as_ptr() as usize,
3594        ))
3595    }
3596    pub fn get_secctx(&self) -> Result<IterableSecctxAttrs<'a>, ErrorContext> {
3597        let mut iter = self.clone();
3598        iter.pos = 0;
3599        for attr in iter {
3600            if let ConntrackAttrs::Secctx(val) = attr? {
3601                return Ok(val);
3602            }
3603        }
3604        Err(ErrorContext::new_missing(
3605            "ConntrackAttrs",
3606            "Secctx",
3607            self.orig_loc,
3608            self.buf.as_ptr() as usize,
3609        ))
3610    }
3611    pub fn get_timestamp(&self) -> Result<u64, ErrorContext> {
3612        let mut iter = self.clone();
3613        iter.pos = 0;
3614        for attr in iter {
3615            if let ConntrackAttrs::Timestamp(val) = attr? {
3616                return Ok(val);
3617            }
3618        }
3619        Err(ErrorContext::new_missing(
3620            "ConntrackAttrs",
3621            "Timestamp",
3622            self.orig_loc,
3623            self.buf.as_ptr() as usize,
3624        ))
3625    }
3626    pub fn get_mark_mask(&self) -> Result<u32, ErrorContext> {
3627        let mut iter = self.clone();
3628        iter.pos = 0;
3629        for attr in iter {
3630            if let ConntrackAttrs::MarkMask(val) = attr? {
3631                return Ok(val);
3632            }
3633        }
3634        Err(ErrorContext::new_missing(
3635            "ConntrackAttrs",
3636            "MarkMask",
3637            self.orig_loc,
3638            self.buf.as_ptr() as usize,
3639        ))
3640    }
3641    pub fn get_labels(&self) -> Result<&'a [u8], ErrorContext> {
3642        let mut iter = self.clone();
3643        iter.pos = 0;
3644        for attr in iter {
3645            if let ConntrackAttrs::Labels(val) = attr? {
3646                return Ok(val);
3647            }
3648        }
3649        Err(ErrorContext::new_missing(
3650            "ConntrackAttrs",
3651            "Labels",
3652            self.orig_loc,
3653            self.buf.as_ptr() as usize,
3654        ))
3655    }
3656    pub fn get_labels_mask(&self) -> Result<&'a [u8], ErrorContext> {
3657        let mut iter = self.clone();
3658        iter.pos = 0;
3659        for attr in iter {
3660            if let ConntrackAttrs::LabelsMask(val) = attr? {
3661                return Ok(val);
3662            }
3663        }
3664        Err(ErrorContext::new_missing(
3665            "ConntrackAttrs",
3666            "LabelsMask",
3667            self.orig_loc,
3668            self.buf.as_ptr() as usize,
3669        ))
3670    }
3671    pub fn get_synproxy(&self) -> Result<IterableSynproxyAttrs<'a>, ErrorContext> {
3672        let mut iter = self.clone();
3673        iter.pos = 0;
3674        for attr in iter {
3675            if let ConntrackAttrs::Synproxy(val) = attr? {
3676                return Ok(val);
3677            }
3678        }
3679        Err(ErrorContext::new_missing(
3680            "ConntrackAttrs",
3681            "Synproxy",
3682            self.orig_loc,
3683            self.buf.as_ptr() as usize,
3684        ))
3685    }
3686    pub fn get_filter(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3687        let mut iter = self.clone();
3688        iter.pos = 0;
3689        for attr in iter {
3690            if let ConntrackAttrs::Filter(val) = attr? {
3691                return Ok(val);
3692            }
3693        }
3694        Err(ErrorContext::new_missing(
3695            "ConntrackAttrs",
3696            "Filter",
3697            self.orig_loc,
3698            self.buf.as_ptr() as usize,
3699        ))
3700    }
3701    #[doc = "conntrack flag bits to change\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
3702    pub fn get_status_mask(&self) -> Result<u32, ErrorContext> {
3703        let mut iter = self.clone();
3704        iter.pos = 0;
3705        for attr in iter {
3706            if let ConntrackAttrs::StatusMask(val) = attr? {
3707                return Ok(val);
3708            }
3709        }
3710        Err(ErrorContext::new_missing(
3711            "ConntrackAttrs",
3712            "StatusMask",
3713            self.orig_loc,
3714            self.buf.as_ptr() as usize,
3715        ))
3716    }
3717    pub fn get_timestamp_event(&self) -> Result<u64, ErrorContext> {
3718        let mut iter = self.clone();
3719        iter.pos = 0;
3720        for attr in iter {
3721            if let ConntrackAttrs::TimestampEvent(val) = attr? {
3722                return Ok(val);
3723            }
3724        }
3725        Err(ErrorContext::new_missing(
3726            "ConntrackAttrs",
3727            "TimestampEvent",
3728            self.orig_loc,
3729            self.buf.as_ptr() as usize,
3730        ))
3731    }
3732}
3733impl ConntrackAttrs<'_> {
3734    pub fn new<'a>(buf: &'a [u8]) -> IterableConntrackAttrs<'a> {
3735        IterableConntrackAttrs::with_loc(buf, buf.as_ptr() as usize)
3736    }
3737    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3738        let res = match r#type {
3739            1u16 => "TupleOrig",
3740            2u16 => "TupleReply",
3741            3u16 => "Status",
3742            4u16 => "Protoinfo",
3743            5u16 => "Help",
3744            6u16 => "NatSrc",
3745            7u16 => "Timeout",
3746            8u16 => "Mark",
3747            9u16 => "CountersOrig",
3748            10u16 => "CountersReply",
3749            11u16 => "Use",
3750            12u16 => "Id",
3751            13u16 => "NatDst",
3752            14u16 => "TupleMaster",
3753            15u16 => "SeqAdjOrig",
3754            16u16 => "SeqAdjReply",
3755            17u16 => "Secmark",
3756            18u16 => "Zone",
3757            19u16 => "Secctx",
3758            20u16 => "Timestamp",
3759            21u16 => "MarkMask",
3760            22u16 => "Labels",
3761            23u16 => "LabelsMask",
3762            24u16 => "Synproxy",
3763            25u16 => "Filter",
3764            26u16 => "StatusMask",
3765            27u16 => "TimestampEvent",
3766            _ => return None,
3767        };
3768        Some(res)
3769    }
3770}
3771#[derive(Clone, Copy, Default)]
3772pub struct IterableConntrackAttrs<'a> {
3773    buf: &'a [u8],
3774    pos: usize,
3775    orig_loc: usize,
3776}
3777impl<'a> IterableConntrackAttrs<'a> {
3778    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3779        Self {
3780            buf,
3781            pos: 0,
3782            orig_loc,
3783        }
3784    }
3785    pub fn get_buf(&self) -> &'a [u8] {
3786        self.buf
3787    }
3788}
3789impl<'a> Iterator for IterableConntrackAttrs<'a> {
3790    type Item = Result<ConntrackAttrs<'a>, ErrorContext>;
3791    fn next(&mut self) -> Option<Self::Item> {
3792        let pos = self.pos;
3793        let mut r#type;
3794        loop {
3795            r#type = None;
3796            if self.buf.len() == self.pos {
3797                return None;
3798            }
3799            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3800                break;
3801            };
3802            r#type = Some(header.r#type);
3803            let res = match header.r#type {
3804                1u16 => ConntrackAttrs::TupleOrig({
3805                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3806                    let Some(val) = res else { break };
3807                    val
3808                }),
3809                2u16 => ConntrackAttrs::TupleReply({
3810                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3811                    let Some(val) = res else { break };
3812                    val
3813                }),
3814                3u16 => ConntrackAttrs::Status({
3815                    let res = parse_be_u32(next);
3816                    let Some(val) = res else { break };
3817                    val
3818                }),
3819                4u16 => ConntrackAttrs::Protoinfo({
3820                    let res = Some(IterableProtoinfoAttrs::with_loc(next, self.orig_loc));
3821                    let Some(val) = res else { break };
3822                    val
3823                }),
3824                5u16 => ConntrackAttrs::Help({
3825                    let res = Some(IterableHelpAttrs::with_loc(next, self.orig_loc));
3826                    let Some(val) = res else { break };
3827                    val
3828                }),
3829                6u16 => ConntrackAttrs::NatSrc({
3830                    let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
3831                    let Some(val) = res else { break };
3832                    val
3833                }),
3834                7u16 => ConntrackAttrs::Timeout({
3835                    let res = parse_be_u32(next);
3836                    let Some(val) = res else { break };
3837                    val
3838                }),
3839                8u16 => ConntrackAttrs::Mark({
3840                    let res = parse_be_u32(next);
3841                    let Some(val) = res else { break };
3842                    val
3843                }),
3844                9u16 => ConntrackAttrs::CountersOrig({
3845                    let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
3846                    let Some(val) = res else { break };
3847                    val
3848                }),
3849                10u16 => ConntrackAttrs::CountersReply({
3850                    let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
3851                    let Some(val) = res else { break };
3852                    val
3853                }),
3854                11u16 => ConntrackAttrs::Use({
3855                    let res = parse_be_u32(next);
3856                    let Some(val) = res else { break };
3857                    val
3858                }),
3859                12u16 => ConntrackAttrs::Id({
3860                    let res = parse_be_u32(next);
3861                    let Some(val) = res else { break };
3862                    val
3863                }),
3864                13u16 => ConntrackAttrs::NatDst({
3865                    let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
3866                    let Some(val) = res else { break };
3867                    val
3868                }),
3869                14u16 => ConntrackAttrs::TupleMaster({
3870                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3871                    let Some(val) = res else { break };
3872                    val
3873                }),
3874                15u16 => ConntrackAttrs::SeqAdjOrig({
3875                    let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
3876                    let Some(val) = res else { break };
3877                    val
3878                }),
3879                16u16 => ConntrackAttrs::SeqAdjReply({
3880                    let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
3881                    let Some(val) = res else { break };
3882                    val
3883                }),
3884                17u16 => ConntrackAttrs::Secmark({
3885                    let res = Some(next);
3886                    let Some(val) = res else { break };
3887                    val
3888                }),
3889                18u16 => ConntrackAttrs::Zone({
3890                    let res = parse_be_u16(next);
3891                    let Some(val) = res else { break };
3892                    val
3893                }),
3894                19u16 => ConntrackAttrs::Secctx({
3895                    let res = Some(IterableSecctxAttrs::with_loc(next, self.orig_loc));
3896                    let Some(val) = res else { break };
3897                    val
3898                }),
3899                20u16 => ConntrackAttrs::Timestamp({
3900                    let res = parse_be_u64(next);
3901                    let Some(val) = res else { break };
3902                    val
3903                }),
3904                21u16 => ConntrackAttrs::MarkMask({
3905                    let res = parse_be_u32(next);
3906                    let Some(val) = res else { break };
3907                    val
3908                }),
3909                22u16 => ConntrackAttrs::Labels({
3910                    let res = Some(next);
3911                    let Some(val) = res else { break };
3912                    val
3913                }),
3914                23u16 => ConntrackAttrs::LabelsMask({
3915                    let res = Some(next);
3916                    let Some(val) = res else { break };
3917                    val
3918                }),
3919                24u16 => ConntrackAttrs::Synproxy({
3920                    let res = Some(IterableSynproxyAttrs::with_loc(next, self.orig_loc));
3921                    let Some(val) = res else { break };
3922                    val
3923                }),
3924                25u16 => ConntrackAttrs::Filter({
3925                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3926                    let Some(val) = res else { break };
3927                    val
3928                }),
3929                26u16 => ConntrackAttrs::StatusMask({
3930                    let res = parse_be_u32(next);
3931                    let Some(val) = res else { break };
3932                    val
3933                }),
3934                27u16 => ConntrackAttrs::TimestampEvent({
3935                    let res = parse_be_u64(next);
3936                    let Some(val) = res else { break };
3937                    val
3938                }),
3939                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3940                n => continue,
3941            };
3942            return Some(Ok(res));
3943        }
3944        Some(Err(ErrorContext::new(
3945            "ConntrackAttrs",
3946            r#type.and_then(|t| ConntrackAttrs::attr_from_type(t)),
3947            self.orig_loc,
3948            self.buf.as_ptr().wrapping_add(pos) as usize,
3949        )))
3950    }
3951}
3952impl<'a> std::fmt::Debug for IterableConntrackAttrs<'_> {
3953    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3954        let mut fmt = f.debug_struct("ConntrackAttrs");
3955        for attr in self.clone() {
3956            let attr = match attr {
3957                Ok(a) => a,
3958                Err(err) => {
3959                    fmt.finish()?;
3960                    f.write_str("Err(")?;
3961                    err.fmt(f)?;
3962                    return f.write_str(")");
3963                }
3964            };
3965            match attr {
3966                ConntrackAttrs::TupleOrig(val) => fmt.field("TupleOrig", &val),
3967                ConntrackAttrs::TupleReply(val) => fmt.field("TupleReply", &val),
3968                ConntrackAttrs::Status(val) => {
3969                    fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
3970                }
3971                ConntrackAttrs::Protoinfo(val) => fmt.field("Protoinfo", &val),
3972                ConntrackAttrs::Help(val) => fmt.field("Help", &val),
3973                ConntrackAttrs::NatSrc(val) => fmt.field("NatSrc", &val),
3974                ConntrackAttrs::Timeout(val) => fmt.field("Timeout", &val),
3975                ConntrackAttrs::Mark(val) => fmt.field("Mark", &val),
3976                ConntrackAttrs::CountersOrig(val) => fmt.field("CountersOrig", &val),
3977                ConntrackAttrs::CountersReply(val) => fmt.field("CountersReply", &val),
3978                ConntrackAttrs::Use(val) => fmt.field("Use", &val),
3979                ConntrackAttrs::Id(val) => fmt.field("Id", &val),
3980                ConntrackAttrs::NatDst(val) => fmt.field("NatDst", &val),
3981                ConntrackAttrs::TupleMaster(val) => fmt.field("TupleMaster", &val),
3982                ConntrackAttrs::SeqAdjOrig(val) => fmt.field("SeqAdjOrig", &val),
3983                ConntrackAttrs::SeqAdjReply(val) => fmt.field("SeqAdjReply", &val),
3984                ConntrackAttrs::Secmark(val) => fmt.field("Secmark", &val),
3985                ConntrackAttrs::Zone(val) => fmt.field("Zone", &val),
3986                ConntrackAttrs::Secctx(val) => fmt.field("Secctx", &val),
3987                ConntrackAttrs::Timestamp(val) => fmt.field("Timestamp", &val),
3988                ConntrackAttrs::MarkMask(val) => fmt.field("MarkMask", &val),
3989                ConntrackAttrs::Labels(val) => fmt.field("Labels", &val),
3990                ConntrackAttrs::LabelsMask(val) => fmt.field("LabelsMask", &val),
3991                ConntrackAttrs::Synproxy(val) => fmt.field("Synproxy", &val),
3992                ConntrackAttrs::Filter(val) => fmt.field("Filter", &val),
3993                ConntrackAttrs::StatusMask(val) => fmt.field(
3994                    "StatusMask",
3995                    &FormatFlags(val.into(), NfCtStatus::from_value),
3996                ),
3997                ConntrackAttrs::TimestampEvent(val) => fmt.field("TimestampEvent", &val),
3998            };
3999        }
4000        fmt.finish()
4001    }
4002}
4003impl IterableConntrackAttrs<'_> {
4004    pub fn lookup_attr(
4005        &self,
4006        offset: usize,
4007        missing_type: Option<u16>,
4008    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4009        let mut stack = Vec::new();
4010        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4011        if cur == offset {
4012            stack.push(("ConntrackAttrs", offset));
4013            return (
4014                stack,
4015                missing_type.and_then(|t| ConntrackAttrs::attr_from_type(t)),
4016            );
4017        }
4018        if cur > offset || cur + self.buf.len() < offset {
4019            return (stack, None);
4020        }
4021        let mut attrs = self.clone();
4022        let mut last_off = cur + attrs.pos;
4023        let mut missing = None;
4024        while let Some(attr) = attrs.next() {
4025            let Ok(attr) = attr else { break };
4026            match attr {
4027                ConntrackAttrs::TupleOrig(val) => {
4028                    (stack, missing) = val.lookup_attr(offset, missing_type);
4029                    if !stack.is_empty() {
4030                        break;
4031                    }
4032                }
4033                ConntrackAttrs::TupleReply(val) => {
4034                    (stack, missing) = val.lookup_attr(offset, missing_type);
4035                    if !stack.is_empty() {
4036                        break;
4037                    }
4038                }
4039                ConntrackAttrs::Status(val) => {
4040                    if last_off == offset {
4041                        stack.push(("Status", last_off));
4042                        break;
4043                    }
4044                }
4045                ConntrackAttrs::Protoinfo(val) => {
4046                    (stack, missing) = val.lookup_attr(offset, missing_type);
4047                    if !stack.is_empty() {
4048                        break;
4049                    }
4050                }
4051                ConntrackAttrs::Help(val) => {
4052                    (stack, missing) = val.lookup_attr(offset, missing_type);
4053                    if !stack.is_empty() {
4054                        break;
4055                    }
4056                }
4057                ConntrackAttrs::NatSrc(val) => {
4058                    (stack, missing) = val.lookup_attr(offset, missing_type);
4059                    if !stack.is_empty() {
4060                        break;
4061                    }
4062                }
4063                ConntrackAttrs::Timeout(val) => {
4064                    if last_off == offset {
4065                        stack.push(("Timeout", last_off));
4066                        break;
4067                    }
4068                }
4069                ConntrackAttrs::Mark(val) => {
4070                    if last_off == offset {
4071                        stack.push(("Mark", last_off));
4072                        break;
4073                    }
4074                }
4075                ConntrackAttrs::CountersOrig(val) => {
4076                    (stack, missing) = val.lookup_attr(offset, missing_type);
4077                    if !stack.is_empty() {
4078                        break;
4079                    }
4080                }
4081                ConntrackAttrs::CountersReply(val) => {
4082                    (stack, missing) = val.lookup_attr(offset, missing_type);
4083                    if !stack.is_empty() {
4084                        break;
4085                    }
4086                }
4087                ConntrackAttrs::Use(val) => {
4088                    if last_off == offset {
4089                        stack.push(("Use", last_off));
4090                        break;
4091                    }
4092                }
4093                ConntrackAttrs::Id(val) => {
4094                    if last_off == offset {
4095                        stack.push(("Id", last_off));
4096                        break;
4097                    }
4098                }
4099                ConntrackAttrs::NatDst(val) => {
4100                    (stack, missing) = val.lookup_attr(offset, missing_type);
4101                    if !stack.is_empty() {
4102                        break;
4103                    }
4104                }
4105                ConntrackAttrs::TupleMaster(val) => {
4106                    (stack, missing) = val.lookup_attr(offset, missing_type);
4107                    if !stack.is_empty() {
4108                        break;
4109                    }
4110                }
4111                ConntrackAttrs::SeqAdjOrig(val) => {
4112                    (stack, missing) = val.lookup_attr(offset, missing_type);
4113                    if !stack.is_empty() {
4114                        break;
4115                    }
4116                }
4117                ConntrackAttrs::SeqAdjReply(val) => {
4118                    (stack, missing) = val.lookup_attr(offset, missing_type);
4119                    if !stack.is_empty() {
4120                        break;
4121                    }
4122                }
4123                ConntrackAttrs::Secmark(val) => {
4124                    if last_off == offset {
4125                        stack.push(("Secmark", last_off));
4126                        break;
4127                    }
4128                }
4129                ConntrackAttrs::Zone(val) => {
4130                    if last_off == offset {
4131                        stack.push(("Zone", last_off));
4132                        break;
4133                    }
4134                }
4135                ConntrackAttrs::Secctx(val) => {
4136                    (stack, missing) = val.lookup_attr(offset, missing_type);
4137                    if !stack.is_empty() {
4138                        break;
4139                    }
4140                }
4141                ConntrackAttrs::Timestamp(val) => {
4142                    if last_off == offset {
4143                        stack.push(("Timestamp", last_off));
4144                        break;
4145                    }
4146                }
4147                ConntrackAttrs::MarkMask(val) => {
4148                    if last_off == offset {
4149                        stack.push(("MarkMask", last_off));
4150                        break;
4151                    }
4152                }
4153                ConntrackAttrs::Labels(val) => {
4154                    if last_off == offset {
4155                        stack.push(("Labels", last_off));
4156                        break;
4157                    }
4158                }
4159                ConntrackAttrs::LabelsMask(val) => {
4160                    if last_off == offset {
4161                        stack.push(("LabelsMask", last_off));
4162                        break;
4163                    }
4164                }
4165                ConntrackAttrs::Synproxy(val) => {
4166                    (stack, missing) = val.lookup_attr(offset, missing_type);
4167                    if !stack.is_empty() {
4168                        break;
4169                    }
4170                }
4171                ConntrackAttrs::Filter(val) => {
4172                    (stack, missing) = val.lookup_attr(offset, missing_type);
4173                    if !stack.is_empty() {
4174                        break;
4175                    }
4176                }
4177                ConntrackAttrs::StatusMask(val) => {
4178                    if last_off == offset {
4179                        stack.push(("StatusMask", last_off));
4180                        break;
4181                    }
4182                }
4183                ConntrackAttrs::TimestampEvent(val) => {
4184                    if last_off == offset {
4185                        stack.push(("TimestampEvent", last_off));
4186                        break;
4187                    }
4188                }
4189                _ => {}
4190            };
4191            last_off = cur + attrs.pos;
4192        }
4193        if !stack.is_empty() {
4194            stack.push(("ConntrackAttrs", cur));
4195        }
4196        (stack, missing)
4197    }
4198}
4199#[derive(Clone)]
4200pub enum ConntrackStatsAttrs {
4201    #[doc = "obsolete"]
4202    Searched(u32),
4203    Found(u32),
4204    #[doc = "obsolete"]
4205    New(u32),
4206    #[doc = "obsolete"]
4207    Invalid(u32),
4208    #[doc = "obsolete"]
4209    Ignore(u32),
4210    #[doc = "obsolete"]
4211    Delete(u32),
4212    #[doc = "obsolete"]
4213    DeleteList(u32),
4214    Insert(u32),
4215    InsertFailed(u32),
4216    Drop(u32),
4217    EarlyDrop(u32),
4218    Error(u32),
4219    SearchRestart(u32),
4220    ClashResolve(u32),
4221    ChainToolong(u32),
4222}
4223impl<'a> IterableConntrackStatsAttrs<'a> {
4224    #[doc = "obsolete"]
4225    pub fn get_searched(&self) -> Result<u32, ErrorContext> {
4226        let mut iter = self.clone();
4227        iter.pos = 0;
4228        for attr in iter {
4229            if let ConntrackStatsAttrs::Searched(val) = attr? {
4230                return Ok(val);
4231            }
4232        }
4233        Err(ErrorContext::new_missing(
4234            "ConntrackStatsAttrs",
4235            "Searched",
4236            self.orig_loc,
4237            self.buf.as_ptr() as usize,
4238        ))
4239    }
4240    pub fn get_found(&self) -> Result<u32, ErrorContext> {
4241        let mut iter = self.clone();
4242        iter.pos = 0;
4243        for attr in iter {
4244            if let ConntrackStatsAttrs::Found(val) = attr? {
4245                return Ok(val);
4246            }
4247        }
4248        Err(ErrorContext::new_missing(
4249            "ConntrackStatsAttrs",
4250            "Found",
4251            self.orig_loc,
4252            self.buf.as_ptr() as usize,
4253        ))
4254    }
4255    #[doc = "obsolete"]
4256    pub fn get_new(&self) -> Result<u32, ErrorContext> {
4257        let mut iter = self.clone();
4258        iter.pos = 0;
4259        for attr in iter {
4260            if let ConntrackStatsAttrs::New(val) = attr? {
4261                return Ok(val);
4262            }
4263        }
4264        Err(ErrorContext::new_missing(
4265            "ConntrackStatsAttrs",
4266            "New",
4267            self.orig_loc,
4268            self.buf.as_ptr() as usize,
4269        ))
4270    }
4271    #[doc = "obsolete"]
4272    pub fn get_invalid(&self) -> Result<u32, ErrorContext> {
4273        let mut iter = self.clone();
4274        iter.pos = 0;
4275        for attr in iter {
4276            if let ConntrackStatsAttrs::Invalid(val) = attr? {
4277                return Ok(val);
4278            }
4279        }
4280        Err(ErrorContext::new_missing(
4281            "ConntrackStatsAttrs",
4282            "Invalid",
4283            self.orig_loc,
4284            self.buf.as_ptr() as usize,
4285        ))
4286    }
4287    #[doc = "obsolete"]
4288    pub fn get_ignore(&self) -> Result<u32, ErrorContext> {
4289        let mut iter = self.clone();
4290        iter.pos = 0;
4291        for attr in iter {
4292            if let ConntrackStatsAttrs::Ignore(val) = attr? {
4293                return Ok(val);
4294            }
4295        }
4296        Err(ErrorContext::new_missing(
4297            "ConntrackStatsAttrs",
4298            "Ignore",
4299            self.orig_loc,
4300            self.buf.as_ptr() as usize,
4301        ))
4302    }
4303    #[doc = "obsolete"]
4304    pub fn get_delete(&self) -> Result<u32, ErrorContext> {
4305        let mut iter = self.clone();
4306        iter.pos = 0;
4307        for attr in iter {
4308            if let ConntrackStatsAttrs::Delete(val) = attr? {
4309                return Ok(val);
4310            }
4311        }
4312        Err(ErrorContext::new_missing(
4313            "ConntrackStatsAttrs",
4314            "Delete",
4315            self.orig_loc,
4316            self.buf.as_ptr() as usize,
4317        ))
4318    }
4319    #[doc = "obsolete"]
4320    pub fn get_delete_list(&self) -> Result<u32, ErrorContext> {
4321        let mut iter = self.clone();
4322        iter.pos = 0;
4323        for attr in iter {
4324            if let ConntrackStatsAttrs::DeleteList(val) = attr? {
4325                return Ok(val);
4326            }
4327        }
4328        Err(ErrorContext::new_missing(
4329            "ConntrackStatsAttrs",
4330            "DeleteList",
4331            self.orig_loc,
4332            self.buf.as_ptr() as usize,
4333        ))
4334    }
4335    pub fn get_insert(&self) -> Result<u32, ErrorContext> {
4336        let mut iter = self.clone();
4337        iter.pos = 0;
4338        for attr in iter {
4339            if let ConntrackStatsAttrs::Insert(val) = attr? {
4340                return Ok(val);
4341            }
4342        }
4343        Err(ErrorContext::new_missing(
4344            "ConntrackStatsAttrs",
4345            "Insert",
4346            self.orig_loc,
4347            self.buf.as_ptr() as usize,
4348        ))
4349    }
4350    pub fn get_insert_failed(&self) -> Result<u32, ErrorContext> {
4351        let mut iter = self.clone();
4352        iter.pos = 0;
4353        for attr in iter {
4354            if let ConntrackStatsAttrs::InsertFailed(val) = attr? {
4355                return Ok(val);
4356            }
4357        }
4358        Err(ErrorContext::new_missing(
4359            "ConntrackStatsAttrs",
4360            "InsertFailed",
4361            self.orig_loc,
4362            self.buf.as_ptr() as usize,
4363        ))
4364    }
4365    pub fn get_drop(&self) -> Result<u32, ErrorContext> {
4366        let mut iter = self.clone();
4367        iter.pos = 0;
4368        for attr in iter {
4369            if let ConntrackStatsAttrs::Drop(val) = attr? {
4370                return Ok(val);
4371            }
4372        }
4373        Err(ErrorContext::new_missing(
4374            "ConntrackStatsAttrs",
4375            "Drop",
4376            self.orig_loc,
4377            self.buf.as_ptr() as usize,
4378        ))
4379    }
4380    pub fn get_early_drop(&self) -> Result<u32, ErrorContext> {
4381        let mut iter = self.clone();
4382        iter.pos = 0;
4383        for attr in iter {
4384            if let ConntrackStatsAttrs::EarlyDrop(val) = attr? {
4385                return Ok(val);
4386            }
4387        }
4388        Err(ErrorContext::new_missing(
4389            "ConntrackStatsAttrs",
4390            "EarlyDrop",
4391            self.orig_loc,
4392            self.buf.as_ptr() as usize,
4393        ))
4394    }
4395    pub fn get_error(&self) -> Result<u32, ErrorContext> {
4396        let mut iter = self.clone();
4397        iter.pos = 0;
4398        for attr in iter {
4399            if let ConntrackStatsAttrs::Error(val) = attr? {
4400                return Ok(val);
4401            }
4402        }
4403        Err(ErrorContext::new_missing(
4404            "ConntrackStatsAttrs",
4405            "Error",
4406            self.orig_loc,
4407            self.buf.as_ptr() as usize,
4408        ))
4409    }
4410    pub fn get_search_restart(&self) -> Result<u32, ErrorContext> {
4411        let mut iter = self.clone();
4412        iter.pos = 0;
4413        for attr in iter {
4414            if let ConntrackStatsAttrs::SearchRestart(val) = attr? {
4415                return Ok(val);
4416            }
4417        }
4418        Err(ErrorContext::new_missing(
4419            "ConntrackStatsAttrs",
4420            "SearchRestart",
4421            self.orig_loc,
4422            self.buf.as_ptr() as usize,
4423        ))
4424    }
4425    pub fn get_clash_resolve(&self) -> Result<u32, ErrorContext> {
4426        let mut iter = self.clone();
4427        iter.pos = 0;
4428        for attr in iter {
4429            if let ConntrackStatsAttrs::ClashResolve(val) = attr? {
4430                return Ok(val);
4431            }
4432        }
4433        Err(ErrorContext::new_missing(
4434            "ConntrackStatsAttrs",
4435            "ClashResolve",
4436            self.orig_loc,
4437            self.buf.as_ptr() as usize,
4438        ))
4439    }
4440    pub fn get_chain_toolong(&self) -> Result<u32, ErrorContext> {
4441        let mut iter = self.clone();
4442        iter.pos = 0;
4443        for attr in iter {
4444            if let ConntrackStatsAttrs::ChainToolong(val) = attr? {
4445                return Ok(val);
4446            }
4447        }
4448        Err(ErrorContext::new_missing(
4449            "ConntrackStatsAttrs",
4450            "ChainToolong",
4451            self.orig_loc,
4452            self.buf.as_ptr() as usize,
4453        ))
4454    }
4455}
4456impl ConntrackStatsAttrs {
4457    pub fn new<'a>(buf: &'a [u8]) -> IterableConntrackStatsAttrs<'a> {
4458        IterableConntrackStatsAttrs::with_loc(buf, buf.as_ptr() as usize)
4459    }
4460    fn attr_from_type(r#type: u16) -> Option<&'static str> {
4461        let res = match r#type {
4462            1u16 => "Searched",
4463            2u16 => "Found",
4464            3u16 => "New",
4465            4u16 => "Invalid",
4466            5u16 => "Ignore",
4467            6u16 => "Delete",
4468            7u16 => "DeleteList",
4469            8u16 => "Insert",
4470            9u16 => "InsertFailed",
4471            10u16 => "Drop",
4472            11u16 => "EarlyDrop",
4473            12u16 => "Error",
4474            13u16 => "SearchRestart",
4475            14u16 => "ClashResolve",
4476            15u16 => "ChainToolong",
4477            _ => return None,
4478        };
4479        Some(res)
4480    }
4481}
4482#[derive(Clone, Copy, Default)]
4483pub struct IterableConntrackStatsAttrs<'a> {
4484    buf: &'a [u8],
4485    pos: usize,
4486    orig_loc: usize,
4487}
4488impl<'a> IterableConntrackStatsAttrs<'a> {
4489    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4490        Self {
4491            buf,
4492            pos: 0,
4493            orig_loc,
4494        }
4495    }
4496    pub fn get_buf(&self) -> &'a [u8] {
4497        self.buf
4498    }
4499}
4500impl<'a> Iterator for IterableConntrackStatsAttrs<'a> {
4501    type Item = Result<ConntrackStatsAttrs, ErrorContext>;
4502    fn next(&mut self) -> Option<Self::Item> {
4503        let pos = self.pos;
4504        let mut r#type;
4505        loop {
4506            r#type = None;
4507            if self.buf.len() == self.pos {
4508                return None;
4509            }
4510            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
4511                break;
4512            };
4513            r#type = Some(header.r#type);
4514            let res = match header.r#type {
4515                1u16 => ConntrackStatsAttrs::Searched({
4516                    let res = parse_be_u32(next);
4517                    let Some(val) = res else { break };
4518                    val
4519                }),
4520                2u16 => ConntrackStatsAttrs::Found({
4521                    let res = parse_be_u32(next);
4522                    let Some(val) = res else { break };
4523                    val
4524                }),
4525                3u16 => ConntrackStatsAttrs::New({
4526                    let res = parse_be_u32(next);
4527                    let Some(val) = res else { break };
4528                    val
4529                }),
4530                4u16 => ConntrackStatsAttrs::Invalid({
4531                    let res = parse_be_u32(next);
4532                    let Some(val) = res else { break };
4533                    val
4534                }),
4535                5u16 => ConntrackStatsAttrs::Ignore({
4536                    let res = parse_be_u32(next);
4537                    let Some(val) = res else { break };
4538                    val
4539                }),
4540                6u16 => ConntrackStatsAttrs::Delete({
4541                    let res = parse_be_u32(next);
4542                    let Some(val) = res else { break };
4543                    val
4544                }),
4545                7u16 => ConntrackStatsAttrs::DeleteList({
4546                    let res = parse_be_u32(next);
4547                    let Some(val) = res else { break };
4548                    val
4549                }),
4550                8u16 => ConntrackStatsAttrs::Insert({
4551                    let res = parse_be_u32(next);
4552                    let Some(val) = res else { break };
4553                    val
4554                }),
4555                9u16 => ConntrackStatsAttrs::InsertFailed({
4556                    let res = parse_be_u32(next);
4557                    let Some(val) = res else { break };
4558                    val
4559                }),
4560                10u16 => ConntrackStatsAttrs::Drop({
4561                    let res = parse_be_u32(next);
4562                    let Some(val) = res else { break };
4563                    val
4564                }),
4565                11u16 => ConntrackStatsAttrs::EarlyDrop({
4566                    let res = parse_be_u32(next);
4567                    let Some(val) = res else { break };
4568                    val
4569                }),
4570                12u16 => ConntrackStatsAttrs::Error({
4571                    let res = parse_be_u32(next);
4572                    let Some(val) = res else { break };
4573                    val
4574                }),
4575                13u16 => ConntrackStatsAttrs::SearchRestart({
4576                    let res = parse_be_u32(next);
4577                    let Some(val) = res else { break };
4578                    val
4579                }),
4580                14u16 => ConntrackStatsAttrs::ClashResolve({
4581                    let res = parse_be_u32(next);
4582                    let Some(val) = res else { break };
4583                    val
4584                }),
4585                15u16 => ConntrackStatsAttrs::ChainToolong({
4586                    let res = parse_be_u32(next);
4587                    let Some(val) = res else { break };
4588                    val
4589                }),
4590                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
4591                n => continue,
4592            };
4593            return Some(Ok(res));
4594        }
4595        Some(Err(ErrorContext::new(
4596            "ConntrackStatsAttrs",
4597            r#type.and_then(|t| ConntrackStatsAttrs::attr_from_type(t)),
4598            self.orig_loc,
4599            self.buf.as_ptr().wrapping_add(pos) as usize,
4600        )))
4601    }
4602}
4603impl std::fmt::Debug for IterableConntrackStatsAttrs<'_> {
4604    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4605        let mut fmt = f.debug_struct("ConntrackStatsAttrs");
4606        for attr in self.clone() {
4607            let attr = match attr {
4608                Ok(a) => a,
4609                Err(err) => {
4610                    fmt.finish()?;
4611                    f.write_str("Err(")?;
4612                    err.fmt(f)?;
4613                    return f.write_str(")");
4614                }
4615            };
4616            match attr {
4617                ConntrackStatsAttrs::Searched(val) => fmt.field("Searched", &val),
4618                ConntrackStatsAttrs::Found(val) => fmt.field("Found", &val),
4619                ConntrackStatsAttrs::New(val) => fmt.field("New", &val),
4620                ConntrackStatsAttrs::Invalid(val) => fmt.field("Invalid", &val),
4621                ConntrackStatsAttrs::Ignore(val) => fmt.field("Ignore", &val),
4622                ConntrackStatsAttrs::Delete(val) => fmt.field("Delete", &val),
4623                ConntrackStatsAttrs::DeleteList(val) => fmt.field("DeleteList", &val),
4624                ConntrackStatsAttrs::Insert(val) => fmt.field("Insert", &val),
4625                ConntrackStatsAttrs::InsertFailed(val) => fmt.field("InsertFailed", &val),
4626                ConntrackStatsAttrs::Drop(val) => fmt.field("Drop", &val),
4627                ConntrackStatsAttrs::EarlyDrop(val) => fmt.field("EarlyDrop", &val),
4628                ConntrackStatsAttrs::Error(val) => fmt.field("Error", &val),
4629                ConntrackStatsAttrs::SearchRestart(val) => fmt.field("SearchRestart", &val),
4630                ConntrackStatsAttrs::ClashResolve(val) => fmt.field("ClashResolve", &val),
4631                ConntrackStatsAttrs::ChainToolong(val) => fmt.field("ChainToolong", &val),
4632            };
4633        }
4634        fmt.finish()
4635    }
4636}
4637impl IterableConntrackStatsAttrs<'_> {
4638    pub fn lookup_attr(
4639        &self,
4640        offset: usize,
4641        missing_type: Option<u16>,
4642    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4643        let mut stack = Vec::new();
4644        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4645        if cur == offset {
4646            stack.push(("ConntrackStatsAttrs", offset));
4647            return (
4648                stack,
4649                missing_type.and_then(|t| ConntrackStatsAttrs::attr_from_type(t)),
4650            );
4651        }
4652        if cur > offset || cur + self.buf.len() < offset {
4653            return (stack, None);
4654        }
4655        let mut attrs = self.clone();
4656        let mut last_off = cur + attrs.pos;
4657        while let Some(attr) = attrs.next() {
4658            let Ok(attr) = attr else { break };
4659            match attr {
4660                ConntrackStatsAttrs::Searched(val) => {
4661                    if last_off == offset {
4662                        stack.push(("Searched", last_off));
4663                        break;
4664                    }
4665                }
4666                ConntrackStatsAttrs::Found(val) => {
4667                    if last_off == offset {
4668                        stack.push(("Found", last_off));
4669                        break;
4670                    }
4671                }
4672                ConntrackStatsAttrs::New(val) => {
4673                    if last_off == offset {
4674                        stack.push(("New", last_off));
4675                        break;
4676                    }
4677                }
4678                ConntrackStatsAttrs::Invalid(val) => {
4679                    if last_off == offset {
4680                        stack.push(("Invalid", last_off));
4681                        break;
4682                    }
4683                }
4684                ConntrackStatsAttrs::Ignore(val) => {
4685                    if last_off == offset {
4686                        stack.push(("Ignore", last_off));
4687                        break;
4688                    }
4689                }
4690                ConntrackStatsAttrs::Delete(val) => {
4691                    if last_off == offset {
4692                        stack.push(("Delete", last_off));
4693                        break;
4694                    }
4695                }
4696                ConntrackStatsAttrs::DeleteList(val) => {
4697                    if last_off == offset {
4698                        stack.push(("DeleteList", last_off));
4699                        break;
4700                    }
4701                }
4702                ConntrackStatsAttrs::Insert(val) => {
4703                    if last_off == offset {
4704                        stack.push(("Insert", last_off));
4705                        break;
4706                    }
4707                }
4708                ConntrackStatsAttrs::InsertFailed(val) => {
4709                    if last_off == offset {
4710                        stack.push(("InsertFailed", last_off));
4711                        break;
4712                    }
4713                }
4714                ConntrackStatsAttrs::Drop(val) => {
4715                    if last_off == offset {
4716                        stack.push(("Drop", last_off));
4717                        break;
4718                    }
4719                }
4720                ConntrackStatsAttrs::EarlyDrop(val) => {
4721                    if last_off == offset {
4722                        stack.push(("EarlyDrop", last_off));
4723                        break;
4724                    }
4725                }
4726                ConntrackStatsAttrs::Error(val) => {
4727                    if last_off == offset {
4728                        stack.push(("Error", last_off));
4729                        break;
4730                    }
4731                }
4732                ConntrackStatsAttrs::SearchRestart(val) => {
4733                    if last_off == offset {
4734                        stack.push(("SearchRestart", last_off));
4735                        break;
4736                    }
4737                }
4738                ConntrackStatsAttrs::ClashResolve(val) => {
4739                    if last_off == offset {
4740                        stack.push(("ClashResolve", last_off));
4741                        break;
4742                    }
4743                }
4744                ConntrackStatsAttrs::ChainToolong(val) => {
4745                    if last_off == offset {
4746                        stack.push(("ChainToolong", last_off));
4747                        break;
4748                    }
4749                }
4750                _ => {}
4751            };
4752            last_off = cur + attrs.pos;
4753        }
4754        if !stack.is_empty() {
4755            stack.push(("ConntrackStatsAttrs", cur));
4756        }
4757        (stack, None)
4758    }
4759}
4760pub struct PushCounterAttrs<Prev: Rec> {
4761    pub(crate) prev: Option<Prev>,
4762    pub(crate) header_offset: Option<usize>,
4763}
4764impl<Prev: Rec> Rec for PushCounterAttrs<Prev> {
4765    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4766        self.prev.as_mut().unwrap().as_rec_mut()
4767    }
4768    fn as_rec(&self) -> &Vec<u8> {
4769        self.prev.as_ref().unwrap().as_rec()
4770    }
4771}
4772impl<Prev: Rec> PushCounterAttrs<Prev> {
4773    pub fn new(prev: Prev) -> Self {
4774        Self {
4775            prev: Some(prev),
4776            header_offset: None,
4777        }
4778    }
4779    pub fn end_nested(mut self) -> Prev {
4780        let mut prev = self.prev.take().unwrap();
4781        if let Some(header_offset) = &self.header_offset {
4782            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4783        }
4784        prev
4785    }
4786    pub fn push_packets(mut self, value: u64) -> Self {
4787        push_header(self.as_rec_mut(), 1u16, 8 as u16);
4788        self.as_rec_mut().extend(value.to_be_bytes());
4789        self
4790    }
4791    pub fn push_bytes(mut self, value: u64) -> Self {
4792        push_header(self.as_rec_mut(), 2u16, 8 as u16);
4793        self.as_rec_mut().extend(value.to_be_bytes());
4794        self
4795    }
4796    pub fn push_packets_old(mut self, value: u32) -> Self {
4797        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4798        self.as_rec_mut().extend(value.to_ne_bytes());
4799        self
4800    }
4801    pub fn push_bytes_old(mut self, value: u32) -> Self {
4802        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4803        self.as_rec_mut().extend(value.to_ne_bytes());
4804        self
4805    }
4806    pub fn push_pad(mut self, value: &[u8]) -> Self {
4807        push_header(self.as_rec_mut(), 5u16, value.len() as u16);
4808        self.as_rec_mut().extend(value);
4809        self
4810    }
4811}
4812impl<Prev: Rec> Drop for PushCounterAttrs<Prev> {
4813    fn drop(&mut self) {
4814        if let Some(prev) = &mut self.prev {
4815            if let Some(header_offset) = &self.header_offset {
4816                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4817            }
4818        }
4819    }
4820}
4821pub struct PushTupleProtoAttrs<Prev: Rec> {
4822    pub(crate) prev: Option<Prev>,
4823    pub(crate) header_offset: Option<usize>,
4824}
4825impl<Prev: Rec> Rec for PushTupleProtoAttrs<Prev> {
4826    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4827        self.prev.as_mut().unwrap().as_rec_mut()
4828    }
4829    fn as_rec(&self) -> &Vec<u8> {
4830        self.prev.as_ref().unwrap().as_rec()
4831    }
4832}
4833impl<Prev: Rec> PushTupleProtoAttrs<Prev> {
4834    pub fn new(prev: Prev) -> Self {
4835        Self {
4836            prev: Some(prev),
4837            header_offset: None,
4838        }
4839    }
4840    pub fn end_nested(mut self) -> Prev {
4841        let mut prev = self.prev.take().unwrap();
4842        if let Some(header_offset) = &self.header_offset {
4843            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4844        }
4845        prev
4846    }
4847    #[doc = "l4 protocol number"]
4848    pub fn push_proto_num(mut self, value: u8) -> Self {
4849        push_header(self.as_rec_mut(), 1u16, 1 as u16);
4850        self.as_rec_mut().extend(value.to_ne_bytes());
4851        self
4852    }
4853    #[doc = "l4 source port"]
4854    pub fn push_proto_src_port(mut self, value: u16) -> Self {
4855        push_header(self.as_rec_mut(), 2u16, 2 as u16);
4856        self.as_rec_mut().extend(value.to_be_bytes());
4857        self
4858    }
4859    #[doc = "l4 source port"]
4860    pub fn push_proto_dst_port(mut self, value: u16) -> Self {
4861        push_header(self.as_rec_mut(), 3u16, 2 as u16);
4862        self.as_rec_mut().extend(value.to_be_bytes());
4863        self
4864    }
4865    #[doc = "l4 icmp id"]
4866    pub fn push_proto_icmp_id(mut self, value: u16) -> Self {
4867        push_header(self.as_rec_mut(), 4u16, 2 as u16);
4868        self.as_rec_mut().extend(value.to_be_bytes());
4869        self
4870    }
4871    pub fn push_proto_icmp_type(mut self, value: u8) -> Self {
4872        push_header(self.as_rec_mut(), 5u16, 1 as u16);
4873        self.as_rec_mut().extend(value.to_ne_bytes());
4874        self
4875    }
4876    pub fn push_proto_icmp_code(mut self, value: u8) -> Self {
4877        push_header(self.as_rec_mut(), 6u16, 1 as u16);
4878        self.as_rec_mut().extend(value.to_ne_bytes());
4879        self
4880    }
4881    #[doc = "l4 icmp id"]
4882    pub fn push_proto_icmpv6_id(mut self, value: u16) -> Self {
4883        push_header(self.as_rec_mut(), 7u16, 2 as u16);
4884        self.as_rec_mut().extend(value.to_be_bytes());
4885        self
4886    }
4887    pub fn push_proto_icmpv6_type(mut self, value: u8) -> Self {
4888        push_header(self.as_rec_mut(), 8u16, 1 as u16);
4889        self.as_rec_mut().extend(value.to_ne_bytes());
4890        self
4891    }
4892    pub fn push_proto_icmpv6_code(mut self, value: u8) -> Self {
4893        push_header(self.as_rec_mut(), 9u16, 1 as u16);
4894        self.as_rec_mut().extend(value.to_ne_bytes());
4895        self
4896    }
4897}
4898impl<Prev: Rec> Drop for PushTupleProtoAttrs<Prev> {
4899    fn drop(&mut self) {
4900        if let Some(prev) = &mut self.prev {
4901            if let Some(header_offset) = &self.header_offset {
4902                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4903            }
4904        }
4905    }
4906}
4907pub struct PushTupleIpAttrs<Prev: Rec> {
4908    pub(crate) prev: Option<Prev>,
4909    pub(crate) header_offset: Option<usize>,
4910}
4911impl<Prev: Rec> Rec for PushTupleIpAttrs<Prev> {
4912    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4913        self.prev.as_mut().unwrap().as_rec_mut()
4914    }
4915    fn as_rec(&self) -> &Vec<u8> {
4916        self.prev.as_ref().unwrap().as_rec()
4917    }
4918}
4919impl<Prev: Rec> PushTupleIpAttrs<Prev> {
4920    pub fn new(prev: Prev) -> Self {
4921        Self {
4922            prev: Some(prev),
4923            header_offset: None,
4924        }
4925    }
4926    pub fn end_nested(mut self) -> Prev {
4927        let mut prev = self.prev.take().unwrap();
4928        if let Some(header_offset) = &self.header_offset {
4929            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4930        }
4931        prev
4932    }
4933    #[doc = "ipv4 source address"]
4934    pub fn push_ip_v4_src(mut self, value: std::net::Ipv4Addr) -> Self {
4935        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4936        self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
4937        self
4938    }
4939    #[doc = "ipv4 destination address"]
4940    pub fn push_ip_v4_dst(mut self, value: std::net::Ipv4Addr) -> Self {
4941        push_header(self.as_rec_mut(), 2u16, 4 as u16);
4942        self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
4943        self
4944    }
4945    #[doc = "ipv6 source address"]
4946    pub fn push_ip_v6_src(mut self, value: std::net::Ipv6Addr) -> Self {
4947        push_header(self.as_rec_mut(), 3u16, 16 as u16);
4948        self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
4949        self
4950    }
4951    #[doc = "ipv6 destination address"]
4952    pub fn push_ip_v6_dst(mut self, value: std::net::Ipv6Addr) -> Self {
4953        push_header(self.as_rec_mut(), 4u16, 16 as u16);
4954        self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
4955        self
4956    }
4957}
4958impl<Prev: Rec> Drop for PushTupleIpAttrs<Prev> {
4959    fn drop(&mut self) {
4960        if let Some(prev) = &mut self.prev {
4961            if let Some(header_offset) = &self.header_offset {
4962                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4963            }
4964        }
4965    }
4966}
4967pub struct PushTupleAttrs<Prev: Rec> {
4968    pub(crate) prev: Option<Prev>,
4969    pub(crate) header_offset: Option<usize>,
4970}
4971impl<Prev: Rec> Rec for PushTupleAttrs<Prev> {
4972    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4973        self.prev.as_mut().unwrap().as_rec_mut()
4974    }
4975    fn as_rec(&self) -> &Vec<u8> {
4976        self.prev.as_ref().unwrap().as_rec()
4977    }
4978}
4979impl<Prev: Rec> PushTupleAttrs<Prev> {
4980    pub fn new(prev: Prev) -> Self {
4981        Self {
4982            prev: Some(prev),
4983            header_offset: None,
4984        }
4985    }
4986    pub fn end_nested(mut self) -> Prev {
4987        let mut prev = self.prev.take().unwrap();
4988        if let Some(header_offset) = &self.header_offset {
4989            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4990        }
4991        prev
4992    }
4993    #[doc = "conntrack l3 information"]
4994    pub fn nested_tuple_ip(mut self) -> PushTupleIpAttrs<Self> {
4995        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
4996        PushTupleIpAttrs {
4997            prev: Some(self),
4998            header_offset: Some(header_offset),
4999        }
5000    }
5001    #[doc = "conntrack l4 information"]
5002    pub fn nested_tuple_proto(mut self) -> PushTupleProtoAttrs<Self> {
5003        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
5004        PushTupleProtoAttrs {
5005            prev: Some(self),
5006            header_offset: Some(header_offset),
5007        }
5008    }
5009    #[doc = "conntrack zone id"]
5010    pub fn push_tuple_zone(mut self, value: u16) -> Self {
5011        push_header(self.as_rec_mut(), 3u16, 2 as u16);
5012        self.as_rec_mut().extend(value.to_be_bytes());
5013        self
5014    }
5015}
5016impl<Prev: Rec> Drop for PushTupleAttrs<Prev> {
5017    fn drop(&mut self) {
5018        if let Some(prev) = &mut self.prev {
5019            if let Some(header_offset) = &self.header_offset {
5020                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5021            }
5022        }
5023    }
5024}
5025pub struct PushProtoinfoTcpAttrs<Prev: Rec> {
5026    pub(crate) prev: Option<Prev>,
5027    pub(crate) header_offset: Option<usize>,
5028}
5029impl<Prev: Rec> Rec for PushProtoinfoTcpAttrs<Prev> {
5030    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5031        self.prev.as_mut().unwrap().as_rec_mut()
5032    }
5033    fn as_rec(&self) -> &Vec<u8> {
5034        self.prev.as_ref().unwrap().as_rec()
5035    }
5036}
5037impl<Prev: Rec> PushProtoinfoTcpAttrs<Prev> {
5038    pub fn new(prev: Prev) -> Self {
5039        Self {
5040            prev: Some(prev),
5041            header_offset: None,
5042        }
5043    }
5044    pub fn end_nested(mut self) -> Prev {
5045        let mut prev = self.prev.take().unwrap();
5046        if let Some(header_offset) = &self.header_offset {
5047            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5048        }
5049        prev
5050    }
5051    #[doc = "tcp connection state\nAssociated type: \"NfCtTcpState\" (enum)"]
5052    pub fn push_tcp_state(mut self, value: u8) -> Self {
5053        push_header(self.as_rec_mut(), 1u16, 1 as u16);
5054        self.as_rec_mut().extend(value.to_ne_bytes());
5055        self
5056    }
5057    #[doc = "window scaling factor in original direction"]
5058    pub fn push_tcp_wscale_original(mut self, value: u8) -> Self {
5059        push_header(self.as_rec_mut(), 2u16, 1 as u16);
5060        self.as_rec_mut().extend(value.to_ne_bytes());
5061        self
5062    }
5063    #[doc = "window scaling factor in reply direction"]
5064    pub fn push_tcp_wscale_reply(mut self, value: u8) -> Self {
5065        push_header(self.as_rec_mut(), 3u16, 1 as u16);
5066        self.as_rec_mut().extend(value.to_ne_bytes());
5067        self
5068    }
5069    pub fn push_tcp_flags_original(mut self, value: PushNfCtTcpFlagsMask) -> Self {
5070        push_header(self.as_rec_mut(), 4u16, value.as_slice().len() as u16);
5071        self.as_rec_mut().extend(value.as_slice());
5072        self
5073    }
5074    pub fn push_tcp_flags_reply(mut self, value: PushNfCtTcpFlagsMask) -> Self {
5075        push_header(self.as_rec_mut(), 5u16, value.as_slice().len() as u16);
5076        self.as_rec_mut().extend(value.as_slice());
5077        self
5078    }
5079}
5080impl<Prev: Rec> Drop for PushProtoinfoTcpAttrs<Prev> {
5081    fn drop(&mut self) {
5082        if let Some(prev) = &mut self.prev {
5083            if let Some(header_offset) = &self.header_offset {
5084                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5085            }
5086        }
5087    }
5088}
5089pub struct PushProtoinfoDccpAttrs<Prev: Rec> {
5090    pub(crate) prev: Option<Prev>,
5091    pub(crate) header_offset: Option<usize>,
5092}
5093impl<Prev: Rec> Rec for PushProtoinfoDccpAttrs<Prev> {
5094    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5095        self.prev.as_mut().unwrap().as_rec_mut()
5096    }
5097    fn as_rec(&self) -> &Vec<u8> {
5098        self.prev.as_ref().unwrap().as_rec()
5099    }
5100}
5101impl<Prev: Rec> PushProtoinfoDccpAttrs<Prev> {
5102    pub fn new(prev: Prev) -> Self {
5103        Self {
5104            prev: Some(prev),
5105            header_offset: None,
5106        }
5107    }
5108    pub fn end_nested(mut self) -> Prev {
5109        let mut prev = self.prev.take().unwrap();
5110        if let Some(header_offset) = &self.header_offset {
5111            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5112        }
5113        prev
5114    }
5115    #[doc = "dccp connection state"]
5116    pub fn push_dccp_state(mut self, value: u8) -> Self {
5117        push_header(self.as_rec_mut(), 1u16, 1 as u16);
5118        self.as_rec_mut().extend(value.to_ne_bytes());
5119        self
5120    }
5121    pub fn push_dccp_role(mut self, value: u8) -> Self {
5122        push_header(self.as_rec_mut(), 2u16, 1 as u16);
5123        self.as_rec_mut().extend(value.to_ne_bytes());
5124        self
5125    }
5126    pub fn push_dccp_handshake_seq(mut self, value: u64) -> Self {
5127        push_header(self.as_rec_mut(), 3u16, 8 as u16);
5128        self.as_rec_mut().extend(value.to_be_bytes());
5129        self
5130    }
5131    pub fn push_dccp_pad(mut self, value: &[u8]) -> Self {
5132        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
5133        self.as_rec_mut().extend(value);
5134        self
5135    }
5136}
5137impl<Prev: Rec> Drop for PushProtoinfoDccpAttrs<Prev> {
5138    fn drop(&mut self) {
5139        if let Some(prev) = &mut self.prev {
5140            if let Some(header_offset) = &self.header_offset {
5141                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5142            }
5143        }
5144    }
5145}
5146pub struct PushProtoinfoSctpAttrs<Prev: Rec> {
5147    pub(crate) prev: Option<Prev>,
5148    pub(crate) header_offset: Option<usize>,
5149}
5150impl<Prev: Rec> Rec for PushProtoinfoSctpAttrs<Prev> {
5151    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5152        self.prev.as_mut().unwrap().as_rec_mut()
5153    }
5154    fn as_rec(&self) -> &Vec<u8> {
5155        self.prev.as_ref().unwrap().as_rec()
5156    }
5157}
5158impl<Prev: Rec> PushProtoinfoSctpAttrs<Prev> {
5159    pub fn new(prev: Prev) -> Self {
5160        Self {
5161            prev: Some(prev),
5162            header_offset: None,
5163        }
5164    }
5165    pub fn end_nested(mut self) -> Prev {
5166        let mut prev = self.prev.take().unwrap();
5167        if let Some(header_offset) = &self.header_offset {
5168            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5169        }
5170        prev
5171    }
5172    #[doc = "sctp connection state\nAssociated type: \"NfCtSctpState\" (enum)"]
5173    pub fn push_sctp_state(mut self, value: u8) -> Self {
5174        push_header(self.as_rec_mut(), 1u16, 1 as u16);
5175        self.as_rec_mut().extend(value.to_ne_bytes());
5176        self
5177    }
5178    pub fn push_vtag_original(mut self, value: u32) -> Self {
5179        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5180        self.as_rec_mut().extend(value.to_be_bytes());
5181        self
5182    }
5183    pub fn push_vtag_reply(mut self, value: u32) -> Self {
5184        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5185        self.as_rec_mut().extend(value.to_be_bytes());
5186        self
5187    }
5188}
5189impl<Prev: Rec> Drop for PushProtoinfoSctpAttrs<Prev> {
5190    fn drop(&mut self) {
5191        if let Some(prev) = &mut self.prev {
5192            if let Some(header_offset) = &self.header_offset {
5193                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5194            }
5195        }
5196    }
5197}
5198pub struct PushProtoinfoAttrs<Prev: Rec> {
5199    pub(crate) prev: Option<Prev>,
5200    pub(crate) header_offset: Option<usize>,
5201}
5202impl<Prev: Rec> Rec for PushProtoinfoAttrs<Prev> {
5203    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5204        self.prev.as_mut().unwrap().as_rec_mut()
5205    }
5206    fn as_rec(&self) -> &Vec<u8> {
5207        self.prev.as_ref().unwrap().as_rec()
5208    }
5209}
5210impl<Prev: Rec> PushProtoinfoAttrs<Prev> {
5211    pub fn new(prev: Prev) -> Self {
5212        Self {
5213            prev: Some(prev),
5214            header_offset: None,
5215        }
5216    }
5217    pub fn end_nested(mut self) -> Prev {
5218        let mut prev = self.prev.take().unwrap();
5219        if let Some(header_offset) = &self.header_offset {
5220            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5221        }
5222        prev
5223    }
5224    #[doc = "conntrack tcp state information"]
5225    pub fn nested_protoinfo_tcp(mut self) -> PushProtoinfoTcpAttrs<Self> {
5226        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
5227        PushProtoinfoTcpAttrs {
5228            prev: Some(self),
5229            header_offset: Some(header_offset),
5230        }
5231    }
5232    #[doc = "conntrack dccp state information"]
5233    pub fn nested_protoinfo_dccp(mut self) -> PushProtoinfoDccpAttrs<Self> {
5234        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
5235        PushProtoinfoDccpAttrs {
5236            prev: Some(self),
5237            header_offset: Some(header_offset),
5238        }
5239    }
5240    #[doc = "conntrack sctp state information"]
5241    pub fn nested_protoinfo_sctp(mut self) -> PushProtoinfoSctpAttrs<Self> {
5242        let header_offset = push_nested_header(self.as_rec_mut(), 3u16);
5243        PushProtoinfoSctpAttrs {
5244            prev: Some(self),
5245            header_offset: Some(header_offset),
5246        }
5247    }
5248}
5249impl<Prev: Rec> Drop for PushProtoinfoAttrs<Prev> {
5250    fn drop(&mut self) {
5251        if let Some(prev) = &mut self.prev {
5252            if let Some(header_offset) = &self.header_offset {
5253                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5254            }
5255        }
5256    }
5257}
5258pub struct PushHelpAttrs<Prev: Rec> {
5259    pub(crate) prev: Option<Prev>,
5260    pub(crate) header_offset: Option<usize>,
5261}
5262impl<Prev: Rec> Rec for PushHelpAttrs<Prev> {
5263    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5264        self.prev.as_mut().unwrap().as_rec_mut()
5265    }
5266    fn as_rec(&self) -> &Vec<u8> {
5267        self.prev.as_ref().unwrap().as_rec()
5268    }
5269}
5270impl<Prev: Rec> PushHelpAttrs<Prev> {
5271    pub fn new(prev: Prev) -> Self {
5272        Self {
5273            prev: Some(prev),
5274            header_offset: None,
5275        }
5276    }
5277    pub fn end_nested(mut self) -> Prev {
5278        let mut prev = self.prev.take().unwrap();
5279        if let Some(header_offset) = &self.header_offset {
5280            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5281        }
5282        prev
5283    }
5284    #[doc = "helper name"]
5285    pub fn push_help_name(mut self, value: &CStr) -> Self {
5286        push_header(
5287            self.as_rec_mut(),
5288            1u16,
5289            value.to_bytes_with_nul().len() as u16,
5290        );
5291        self.as_rec_mut().extend(value.to_bytes_with_nul());
5292        self
5293    }
5294    #[doc = "helper name"]
5295    pub fn push_help_name_bytes(mut self, value: &[u8]) -> Self {
5296        push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
5297        self.as_rec_mut().extend(value);
5298        self.as_rec_mut().push(0);
5299        self
5300    }
5301}
5302impl<Prev: Rec> Drop for PushHelpAttrs<Prev> {
5303    fn drop(&mut self) {
5304        if let Some(prev) = &mut self.prev {
5305            if let Some(header_offset) = &self.header_offset {
5306                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5307            }
5308        }
5309    }
5310}
5311pub struct PushNatProtoAttrs<Prev: Rec> {
5312    pub(crate) prev: Option<Prev>,
5313    pub(crate) header_offset: Option<usize>,
5314}
5315impl<Prev: Rec> Rec for PushNatProtoAttrs<Prev> {
5316    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5317        self.prev.as_mut().unwrap().as_rec_mut()
5318    }
5319    fn as_rec(&self) -> &Vec<u8> {
5320        self.prev.as_ref().unwrap().as_rec()
5321    }
5322}
5323impl<Prev: Rec> PushNatProtoAttrs<Prev> {
5324    pub fn new(prev: Prev) -> Self {
5325        Self {
5326            prev: Some(prev),
5327            header_offset: None,
5328        }
5329    }
5330    pub fn end_nested(mut self) -> Prev {
5331        let mut prev = self.prev.take().unwrap();
5332        if let Some(header_offset) = &self.header_offset {
5333            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5334        }
5335        prev
5336    }
5337    pub fn push_nat_port_min(mut self, value: u16) -> Self {
5338        push_header(self.as_rec_mut(), 1u16, 2 as u16);
5339        self.as_rec_mut().extend(value.to_be_bytes());
5340        self
5341    }
5342    pub fn push_nat_port_max(mut self, value: u16) -> Self {
5343        push_header(self.as_rec_mut(), 2u16, 2 as u16);
5344        self.as_rec_mut().extend(value.to_be_bytes());
5345        self
5346    }
5347}
5348impl<Prev: Rec> Drop for PushNatProtoAttrs<Prev> {
5349    fn drop(&mut self) {
5350        if let Some(prev) = &mut self.prev {
5351            if let Some(header_offset) = &self.header_offset {
5352                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5353            }
5354        }
5355    }
5356}
5357pub struct PushNatAttrs<Prev: Rec> {
5358    pub(crate) prev: Option<Prev>,
5359    pub(crate) header_offset: Option<usize>,
5360}
5361impl<Prev: Rec> Rec for PushNatAttrs<Prev> {
5362    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5363        self.prev.as_mut().unwrap().as_rec_mut()
5364    }
5365    fn as_rec(&self) -> &Vec<u8> {
5366        self.prev.as_ref().unwrap().as_rec()
5367    }
5368}
5369impl<Prev: Rec> PushNatAttrs<Prev> {
5370    pub fn new(prev: Prev) -> Self {
5371        Self {
5372            prev: Some(prev),
5373            header_offset: None,
5374        }
5375    }
5376    pub fn end_nested(mut self) -> Prev {
5377        let mut prev = self.prev.take().unwrap();
5378        if let Some(header_offset) = &self.header_offset {
5379            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5380        }
5381        prev
5382    }
5383    pub fn push_nat_v4_minip(mut self, value: u32) -> Self {
5384        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5385        self.as_rec_mut().extend(value.to_be_bytes());
5386        self
5387    }
5388    pub fn push_nat_v4_maxip(mut self, value: u32) -> Self {
5389        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5390        self.as_rec_mut().extend(value.to_be_bytes());
5391        self
5392    }
5393    pub fn push_nat_v6_minip(mut self, value: &[u8]) -> Self {
5394        push_header(self.as_rec_mut(), 3u16, value.len() as u16);
5395        self.as_rec_mut().extend(value);
5396        self
5397    }
5398    pub fn push_nat_v6_maxip(mut self, value: &[u8]) -> Self {
5399        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
5400        self.as_rec_mut().extend(value);
5401        self
5402    }
5403    pub fn nested_nat_proto(mut self) -> PushNatProtoAttrs<Self> {
5404        let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
5405        PushNatProtoAttrs {
5406            prev: Some(self),
5407            header_offset: Some(header_offset),
5408        }
5409    }
5410}
5411impl<Prev: Rec> Drop for PushNatAttrs<Prev> {
5412    fn drop(&mut self) {
5413        if let Some(prev) = &mut self.prev {
5414            if let Some(header_offset) = &self.header_offset {
5415                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5416            }
5417        }
5418    }
5419}
5420pub struct PushSeqadjAttrs<Prev: Rec> {
5421    pub(crate) prev: Option<Prev>,
5422    pub(crate) header_offset: Option<usize>,
5423}
5424impl<Prev: Rec> Rec for PushSeqadjAttrs<Prev> {
5425    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5426        self.prev.as_mut().unwrap().as_rec_mut()
5427    }
5428    fn as_rec(&self) -> &Vec<u8> {
5429        self.prev.as_ref().unwrap().as_rec()
5430    }
5431}
5432impl<Prev: Rec> PushSeqadjAttrs<Prev> {
5433    pub fn new(prev: Prev) -> Self {
5434        Self {
5435            prev: Some(prev),
5436            header_offset: None,
5437        }
5438    }
5439    pub fn end_nested(mut self) -> Prev {
5440        let mut prev = self.prev.take().unwrap();
5441        if let Some(header_offset) = &self.header_offset {
5442            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5443        }
5444        prev
5445    }
5446    pub fn push_correction_pos(mut self, value: u32) -> Self {
5447        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5448        self.as_rec_mut().extend(value.to_be_bytes());
5449        self
5450    }
5451    pub fn push_offset_before(mut self, value: u32) -> Self {
5452        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5453        self.as_rec_mut().extend(value.to_be_bytes());
5454        self
5455    }
5456    pub fn push_offset_after(mut self, value: u32) -> Self {
5457        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5458        self.as_rec_mut().extend(value.to_be_bytes());
5459        self
5460    }
5461}
5462impl<Prev: Rec> Drop for PushSeqadjAttrs<Prev> {
5463    fn drop(&mut self) {
5464        if let Some(prev) = &mut self.prev {
5465            if let Some(header_offset) = &self.header_offset {
5466                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5467            }
5468        }
5469    }
5470}
5471pub struct PushSecctxAttrs<Prev: Rec> {
5472    pub(crate) prev: Option<Prev>,
5473    pub(crate) header_offset: Option<usize>,
5474}
5475impl<Prev: Rec> Rec for PushSecctxAttrs<Prev> {
5476    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5477        self.prev.as_mut().unwrap().as_rec_mut()
5478    }
5479    fn as_rec(&self) -> &Vec<u8> {
5480        self.prev.as_ref().unwrap().as_rec()
5481    }
5482}
5483impl<Prev: Rec> PushSecctxAttrs<Prev> {
5484    pub fn new(prev: Prev) -> Self {
5485        Self {
5486            prev: Some(prev),
5487            header_offset: None,
5488        }
5489    }
5490    pub fn end_nested(mut self) -> Prev {
5491        let mut prev = self.prev.take().unwrap();
5492        if let Some(header_offset) = &self.header_offset {
5493            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5494        }
5495        prev
5496    }
5497    pub fn push_secctx_name(mut self, value: &CStr) -> Self {
5498        push_header(
5499            self.as_rec_mut(),
5500            1u16,
5501            value.to_bytes_with_nul().len() as u16,
5502        );
5503        self.as_rec_mut().extend(value.to_bytes_with_nul());
5504        self
5505    }
5506    pub fn push_secctx_name_bytes(mut self, value: &[u8]) -> Self {
5507        push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
5508        self.as_rec_mut().extend(value);
5509        self.as_rec_mut().push(0);
5510        self
5511    }
5512}
5513impl<Prev: Rec> Drop for PushSecctxAttrs<Prev> {
5514    fn drop(&mut self) {
5515        if let Some(prev) = &mut self.prev {
5516            if let Some(header_offset) = &self.header_offset {
5517                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5518            }
5519        }
5520    }
5521}
5522pub struct PushSynproxyAttrs<Prev: Rec> {
5523    pub(crate) prev: Option<Prev>,
5524    pub(crate) header_offset: Option<usize>,
5525}
5526impl<Prev: Rec> Rec for PushSynproxyAttrs<Prev> {
5527    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5528        self.prev.as_mut().unwrap().as_rec_mut()
5529    }
5530    fn as_rec(&self) -> &Vec<u8> {
5531        self.prev.as_ref().unwrap().as_rec()
5532    }
5533}
5534impl<Prev: Rec> PushSynproxyAttrs<Prev> {
5535    pub fn new(prev: Prev) -> Self {
5536        Self {
5537            prev: Some(prev),
5538            header_offset: None,
5539        }
5540    }
5541    pub fn end_nested(mut self) -> Prev {
5542        let mut prev = self.prev.take().unwrap();
5543        if let Some(header_offset) = &self.header_offset {
5544            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5545        }
5546        prev
5547    }
5548    pub fn push_isn(mut self, value: u32) -> Self {
5549        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5550        self.as_rec_mut().extend(value.to_be_bytes());
5551        self
5552    }
5553    pub fn push_its(mut self, value: u32) -> Self {
5554        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5555        self.as_rec_mut().extend(value.to_be_bytes());
5556        self
5557    }
5558    pub fn push_tsoff(mut self, value: u32) -> Self {
5559        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5560        self.as_rec_mut().extend(value.to_be_bytes());
5561        self
5562    }
5563}
5564impl<Prev: Rec> Drop for PushSynproxyAttrs<Prev> {
5565    fn drop(&mut self) {
5566        if let Some(prev) = &mut self.prev {
5567            if let Some(header_offset) = &self.header_offset {
5568                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5569            }
5570        }
5571    }
5572}
5573pub struct PushConntrackAttrs<Prev: Rec> {
5574    pub(crate) prev: Option<Prev>,
5575    pub(crate) header_offset: Option<usize>,
5576}
5577impl<Prev: Rec> Rec for PushConntrackAttrs<Prev> {
5578    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5579        self.prev.as_mut().unwrap().as_rec_mut()
5580    }
5581    fn as_rec(&self) -> &Vec<u8> {
5582        self.prev.as_ref().unwrap().as_rec()
5583    }
5584}
5585impl<Prev: Rec> PushConntrackAttrs<Prev> {
5586    pub fn new(prev: Prev) -> Self {
5587        Self {
5588            prev: Some(prev),
5589            header_offset: None,
5590        }
5591    }
5592    pub fn end_nested(mut self) -> Prev {
5593        let mut prev = self.prev.take().unwrap();
5594        if let Some(header_offset) = &self.header_offset {
5595            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5596        }
5597        prev
5598    }
5599    #[doc = "conntrack l3+l4 protocol information, original direction"]
5600    pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
5601        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
5602        PushTupleAttrs {
5603            prev: Some(self),
5604            header_offset: Some(header_offset),
5605        }
5606    }
5607    #[doc = "conntrack l3+l4 protocol information, reply direction"]
5608    pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
5609        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
5610        PushTupleAttrs {
5611            prev: Some(self),
5612            header_offset: Some(header_offset),
5613        }
5614    }
5615    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
5616    pub fn push_status(mut self, value: u32) -> Self {
5617        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5618        self.as_rec_mut().extend(value.to_be_bytes());
5619        self
5620    }
5621    pub fn nested_protoinfo(mut self) -> PushProtoinfoAttrs<Self> {
5622        let header_offset = push_nested_header(self.as_rec_mut(), 4u16);
5623        PushProtoinfoAttrs {
5624            prev: Some(self),
5625            header_offset: Some(header_offset),
5626        }
5627    }
5628    pub fn nested_help(mut self) -> PushHelpAttrs<Self> {
5629        let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
5630        PushHelpAttrs {
5631            prev: Some(self),
5632            header_offset: Some(header_offset),
5633        }
5634    }
5635    pub fn nested_nat_src(mut self) -> PushNatAttrs<Self> {
5636        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
5637        PushNatAttrs {
5638            prev: Some(self),
5639            header_offset: Some(header_offset),
5640        }
5641    }
5642    pub fn push_timeout(mut self, value: u32) -> Self {
5643        push_header(self.as_rec_mut(), 7u16, 4 as u16);
5644        self.as_rec_mut().extend(value.to_be_bytes());
5645        self
5646    }
5647    pub fn push_mark(mut self, value: u32) -> Self {
5648        push_header(self.as_rec_mut(), 8u16, 4 as u16);
5649        self.as_rec_mut().extend(value.to_be_bytes());
5650        self
5651    }
5652    pub fn nested_counters_orig(mut self) -> PushCounterAttrs<Self> {
5653        let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
5654        PushCounterAttrs {
5655            prev: Some(self),
5656            header_offset: Some(header_offset),
5657        }
5658    }
5659    pub fn nested_counters_reply(mut self) -> PushCounterAttrs<Self> {
5660        let header_offset = push_nested_header(self.as_rec_mut(), 10u16);
5661        PushCounterAttrs {
5662            prev: Some(self),
5663            header_offset: Some(header_offset),
5664        }
5665    }
5666    pub fn push_use(mut self, value: u32) -> Self {
5667        push_header(self.as_rec_mut(), 11u16, 4 as u16);
5668        self.as_rec_mut().extend(value.to_be_bytes());
5669        self
5670    }
5671    pub fn push_id(mut self, value: u32) -> Self {
5672        push_header(self.as_rec_mut(), 12u16, 4 as u16);
5673        self.as_rec_mut().extend(value.to_be_bytes());
5674        self
5675    }
5676    pub fn nested_nat_dst(mut self) -> PushNatAttrs<Self> {
5677        let header_offset = push_nested_header(self.as_rec_mut(), 13u16);
5678        PushNatAttrs {
5679            prev: Some(self),
5680            header_offset: Some(header_offset),
5681        }
5682    }
5683    pub fn nested_tuple_master(mut self) -> PushTupleAttrs<Self> {
5684        let header_offset = push_nested_header(self.as_rec_mut(), 14u16);
5685        PushTupleAttrs {
5686            prev: Some(self),
5687            header_offset: Some(header_offset),
5688        }
5689    }
5690    pub fn nested_seq_adj_orig(mut self) -> PushSeqadjAttrs<Self> {
5691        let header_offset = push_nested_header(self.as_rec_mut(), 15u16);
5692        PushSeqadjAttrs {
5693            prev: Some(self),
5694            header_offset: Some(header_offset),
5695        }
5696    }
5697    pub fn nested_seq_adj_reply(mut self) -> PushSeqadjAttrs<Self> {
5698        let header_offset = push_nested_header(self.as_rec_mut(), 16u16);
5699        PushSeqadjAttrs {
5700            prev: Some(self),
5701            header_offset: Some(header_offset),
5702        }
5703    }
5704    #[doc = "obsolete"]
5705    pub fn push_secmark(mut self, value: &[u8]) -> Self {
5706        push_header(self.as_rec_mut(), 17u16, value.len() as u16);
5707        self.as_rec_mut().extend(value);
5708        self
5709    }
5710    #[doc = "conntrack zone id"]
5711    pub fn push_zone(mut self, value: u16) -> Self {
5712        push_header(self.as_rec_mut(), 18u16, 2 as u16);
5713        self.as_rec_mut().extend(value.to_be_bytes());
5714        self
5715    }
5716    pub fn nested_secctx(mut self) -> PushSecctxAttrs<Self> {
5717        let header_offset = push_nested_header(self.as_rec_mut(), 19u16);
5718        PushSecctxAttrs {
5719            prev: Some(self),
5720            header_offset: Some(header_offset),
5721        }
5722    }
5723    pub fn push_timestamp(mut self, value: u64) -> Self {
5724        push_header(self.as_rec_mut(), 20u16, 8 as u16);
5725        self.as_rec_mut().extend(value.to_be_bytes());
5726        self
5727    }
5728    pub fn push_mark_mask(mut self, value: u32) -> Self {
5729        push_header(self.as_rec_mut(), 21u16, 4 as u16);
5730        self.as_rec_mut().extend(value.to_be_bytes());
5731        self
5732    }
5733    pub fn push_labels(mut self, value: &[u8]) -> Self {
5734        push_header(self.as_rec_mut(), 22u16, value.len() as u16);
5735        self.as_rec_mut().extend(value);
5736        self
5737    }
5738    pub fn push_labels_mask(mut self, value: &[u8]) -> Self {
5739        push_header(self.as_rec_mut(), 23u16, value.len() as u16);
5740        self.as_rec_mut().extend(value);
5741        self
5742    }
5743    pub fn nested_synproxy(mut self) -> PushSynproxyAttrs<Self> {
5744        let header_offset = push_nested_header(self.as_rec_mut(), 24u16);
5745        PushSynproxyAttrs {
5746            prev: Some(self),
5747            header_offset: Some(header_offset),
5748        }
5749    }
5750    pub fn nested_filter(mut self) -> PushTupleAttrs<Self> {
5751        let header_offset = push_nested_header(self.as_rec_mut(), 25u16);
5752        PushTupleAttrs {
5753            prev: Some(self),
5754            header_offset: Some(header_offset),
5755        }
5756    }
5757    #[doc = "conntrack flag bits to change\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
5758    pub fn push_status_mask(mut self, value: u32) -> Self {
5759        push_header(self.as_rec_mut(), 26u16, 4 as u16);
5760        self.as_rec_mut().extend(value.to_be_bytes());
5761        self
5762    }
5763    pub fn push_timestamp_event(mut self, value: u64) -> Self {
5764        push_header(self.as_rec_mut(), 27u16, 8 as u16);
5765        self.as_rec_mut().extend(value.to_be_bytes());
5766        self
5767    }
5768}
5769impl<Prev: Rec> Drop for PushConntrackAttrs<Prev> {
5770    fn drop(&mut self) {
5771        if let Some(prev) = &mut self.prev {
5772            if let Some(header_offset) = &self.header_offset {
5773                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5774            }
5775        }
5776    }
5777}
5778pub struct PushConntrackStatsAttrs<Prev: Rec> {
5779    pub(crate) prev: Option<Prev>,
5780    pub(crate) header_offset: Option<usize>,
5781}
5782impl<Prev: Rec> Rec for PushConntrackStatsAttrs<Prev> {
5783    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5784        self.prev.as_mut().unwrap().as_rec_mut()
5785    }
5786    fn as_rec(&self) -> &Vec<u8> {
5787        self.prev.as_ref().unwrap().as_rec()
5788    }
5789}
5790impl<Prev: Rec> PushConntrackStatsAttrs<Prev> {
5791    pub fn new(prev: Prev) -> Self {
5792        Self {
5793            prev: Some(prev),
5794            header_offset: None,
5795        }
5796    }
5797    pub fn end_nested(mut self) -> Prev {
5798        let mut prev = self.prev.take().unwrap();
5799        if let Some(header_offset) = &self.header_offset {
5800            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5801        }
5802        prev
5803    }
5804    #[doc = "obsolete"]
5805    pub fn push_searched(mut self, value: u32) -> Self {
5806        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5807        self.as_rec_mut().extend(value.to_be_bytes());
5808        self
5809    }
5810    pub fn push_found(mut self, value: u32) -> Self {
5811        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5812        self.as_rec_mut().extend(value.to_be_bytes());
5813        self
5814    }
5815    #[doc = "obsolete"]
5816    pub fn push_new(mut self, value: u32) -> Self {
5817        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5818        self.as_rec_mut().extend(value.to_be_bytes());
5819        self
5820    }
5821    #[doc = "obsolete"]
5822    pub fn push_invalid(mut self, value: u32) -> Self {
5823        push_header(self.as_rec_mut(), 4u16, 4 as u16);
5824        self.as_rec_mut().extend(value.to_be_bytes());
5825        self
5826    }
5827    #[doc = "obsolete"]
5828    pub fn push_ignore(mut self, value: u32) -> Self {
5829        push_header(self.as_rec_mut(), 5u16, 4 as u16);
5830        self.as_rec_mut().extend(value.to_be_bytes());
5831        self
5832    }
5833    #[doc = "obsolete"]
5834    pub fn push_delete(mut self, value: u32) -> Self {
5835        push_header(self.as_rec_mut(), 6u16, 4 as u16);
5836        self.as_rec_mut().extend(value.to_be_bytes());
5837        self
5838    }
5839    #[doc = "obsolete"]
5840    pub fn push_delete_list(mut self, value: u32) -> Self {
5841        push_header(self.as_rec_mut(), 7u16, 4 as u16);
5842        self.as_rec_mut().extend(value.to_be_bytes());
5843        self
5844    }
5845    pub fn push_insert(mut self, value: u32) -> Self {
5846        push_header(self.as_rec_mut(), 8u16, 4 as u16);
5847        self.as_rec_mut().extend(value.to_be_bytes());
5848        self
5849    }
5850    pub fn push_insert_failed(mut self, value: u32) -> Self {
5851        push_header(self.as_rec_mut(), 9u16, 4 as u16);
5852        self.as_rec_mut().extend(value.to_be_bytes());
5853        self
5854    }
5855    pub fn push_drop(mut self, value: u32) -> Self {
5856        push_header(self.as_rec_mut(), 10u16, 4 as u16);
5857        self.as_rec_mut().extend(value.to_be_bytes());
5858        self
5859    }
5860    pub fn push_early_drop(mut self, value: u32) -> Self {
5861        push_header(self.as_rec_mut(), 11u16, 4 as u16);
5862        self.as_rec_mut().extend(value.to_be_bytes());
5863        self
5864    }
5865    pub fn push_error(mut self, value: u32) -> Self {
5866        push_header(self.as_rec_mut(), 12u16, 4 as u16);
5867        self.as_rec_mut().extend(value.to_be_bytes());
5868        self
5869    }
5870    pub fn push_search_restart(mut self, value: u32) -> Self {
5871        push_header(self.as_rec_mut(), 13u16, 4 as u16);
5872        self.as_rec_mut().extend(value.to_be_bytes());
5873        self
5874    }
5875    pub fn push_clash_resolve(mut self, value: u32) -> Self {
5876        push_header(self.as_rec_mut(), 14u16, 4 as u16);
5877        self.as_rec_mut().extend(value.to_be_bytes());
5878        self
5879    }
5880    pub fn push_chain_toolong(mut self, value: u32) -> Self {
5881        push_header(self.as_rec_mut(), 15u16, 4 as u16);
5882        self.as_rec_mut().extend(value.to_be_bytes());
5883        self
5884    }
5885}
5886impl<Prev: Rec> Drop for PushConntrackStatsAttrs<Prev> {
5887    fn drop(&mut self) {
5888        if let Some(prev) = &mut self.prev {
5889            if let Some(header_offset) = &self.header_offset {
5890                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5891            }
5892        }
5893    }
5894}
5895#[derive(Clone)]
5896pub struct PushNfgenmsg {
5897    pub(crate) buf: [u8; 4usize],
5898}
5899#[doc = "Create zero-initialized struct"]
5900impl Default for PushNfgenmsg {
5901    fn default() -> Self {
5902        Self { buf: [0u8; 4usize] }
5903    }
5904}
5905impl PushNfgenmsg {
5906    #[doc = "Create zero-initialized struct"]
5907    pub fn new() -> Self {
5908        Default::default()
5909    }
5910    #[doc = "Copy from contents from other slice"]
5911    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
5912        if other.len() != Self::len() {
5913            return None;
5914        }
5915        let mut buf = [0u8; Self::len()];
5916        buf.clone_from_slice(other);
5917        Some(Self { buf })
5918    }
5919    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
5920    pub fn new_from_zeroed(other: &[u8]) -> Self {
5921        let mut buf = [0u8; Self::len()];
5922        let len = buf.len().min(other.len());
5923        buf[..len].clone_from_slice(&other[..len]);
5924        Self { buf }
5925    }
5926    pub fn as_slice(&self) -> &[u8] {
5927        &self.buf
5928    }
5929    pub fn as_mut_slice(&mut self) -> &mut [u8] {
5930        &mut self.buf
5931    }
5932    pub const fn len() -> usize {
5933        4usize
5934    }
5935    pub fn nfgen_family(&self) -> u8 {
5936        parse_u8(&self.buf[0usize..1usize]).unwrap()
5937    }
5938    pub fn set_nfgen_family(&mut self, value: u8) {
5939        self.buf[0usize..1usize].copy_from_slice(&value.to_ne_bytes())
5940    }
5941    pub fn version(&self) -> u8 {
5942        parse_u8(&self.buf[1usize..2usize]).unwrap()
5943    }
5944    pub fn set_version(&mut self, value: u8) {
5945        self.buf[1usize..2usize].copy_from_slice(&value.to_ne_bytes())
5946    }
5947    pub fn res_id(&self) -> u16 {
5948        parse_be_u16(&self.buf[2usize..4usize]).unwrap()
5949    }
5950    pub fn set_res_id(&mut self, value: u16) {
5951        self.buf[2usize..4usize].copy_from_slice(&value.to_be_bytes())
5952    }
5953}
5954impl std::fmt::Debug for PushNfgenmsg {
5955    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5956        fmt.debug_struct("Nfgenmsg")
5957            .field("nfgen_family", &self.nfgen_family())
5958            .field("version", &self.version())
5959            .field("res_id", &self.res_id())
5960            .finish()
5961    }
5962}
5963#[derive(Clone)]
5964pub struct PushNfCtTcpFlagsMask {
5965    pub(crate) buf: [u8; 2usize],
5966}
5967#[doc = "Create zero-initialized struct"]
5968impl Default for PushNfCtTcpFlagsMask {
5969    fn default() -> Self {
5970        Self { buf: [0u8; 2usize] }
5971    }
5972}
5973impl PushNfCtTcpFlagsMask {
5974    #[doc = "Create zero-initialized struct"]
5975    pub fn new() -> Self {
5976        Default::default()
5977    }
5978    #[doc = "Copy from contents from other slice"]
5979    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
5980        if other.len() != Self::len() {
5981            return None;
5982        }
5983        let mut buf = [0u8; Self::len()];
5984        buf.clone_from_slice(other);
5985        Some(Self { buf })
5986    }
5987    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
5988    pub fn new_from_zeroed(other: &[u8]) -> Self {
5989        let mut buf = [0u8; Self::len()];
5990        let len = buf.len().min(other.len());
5991        buf[..len].clone_from_slice(&other[..len]);
5992        Self { buf }
5993    }
5994    pub fn as_slice(&self) -> &[u8] {
5995        &self.buf
5996    }
5997    pub fn as_mut_slice(&mut self) -> &mut [u8] {
5998        &mut self.buf
5999    }
6000    pub const fn len() -> usize {
6001        2usize
6002    }
6003    #[doc = "Associated type: \"NfCtTcpFlags\" (1 bit per enumeration)"]
6004    pub fn flags(&self) -> u8 {
6005        parse_u8(&self.buf[0usize..1usize]).unwrap()
6006    }
6007    #[doc = "Associated type: \"NfCtTcpFlags\" (1 bit per enumeration)"]
6008    pub fn set_flags(&mut self, value: u8) {
6009        self.buf[0usize..1usize].copy_from_slice(&value.to_ne_bytes())
6010    }
6011    #[doc = "Associated type: \"NfCtTcpFlags\" (1 bit per enumeration)"]
6012    pub fn mask(&self) -> u8 {
6013        parse_u8(&self.buf[1usize..2usize]).unwrap()
6014    }
6015    #[doc = "Associated type: \"NfCtTcpFlags\" (1 bit per enumeration)"]
6016    pub fn set_mask(&mut self, value: u8) {
6017        self.buf[1usize..2usize].copy_from_slice(&value.to_ne_bytes())
6018    }
6019}
6020impl std::fmt::Debug for PushNfCtTcpFlagsMask {
6021    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6022        fmt.debug_struct("NfCtTcpFlagsMask")
6023            .field(
6024                "flags",
6025                &FormatFlags(self.flags().into(), NfCtTcpFlags::from_value),
6026            )
6027            .field(
6028                "mask",
6029                &FormatFlags(self.mask().into(), NfCtTcpFlags::from_value),
6030            )
6031            .finish()
6032    }
6033}
6034#[doc = "get / dump entries"]
6035pub struct PushOpGetDumpRequest<Prev: Rec> {
6036    pub(crate) prev: Option<Prev>,
6037    pub(crate) header_offset: Option<usize>,
6038}
6039impl<Prev: Rec> Rec for PushOpGetDumpRequest<Prev> {
6040    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6041        self.prev.as_mut().unwrap().as_rec_mut()
6042    }
6043    fn as_rec(&self) -> &Vec<u8> {
6044        self.prev.as_ref().unwrap().as_rec()
6045    }
6046}
6047impl<Prev: Rec> PushOpGetDumpRequest<Prev> {
6048    pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
6049        Self::write_header(&mut prev, header);
6050        Self::new_without_header(prev)
6051    }
6052    fn new_without_header(prev: Prev) -> Self {
6053        Self {
6054            prev: Some(prev),
6055            header_offset: None,
6056        }
6057    }
6058    fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
6059        prev.as_rec_mut().extend(header.as_slice());
6060    }
6061    pub fn end_nested(mut self) -> Prev {
6062        let mut prev = self.prev.take().unwrap();
6063        if let Some(header_offset) = &self.header_offset {
6064            finalize_nested_header(prev.as_rec_mut(), *header_offset);
6065        }
6066        prev
6067    }
6068    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6069    pub fn push_status(mut self, value: u32) -> Self {
6070        push_header(self.as_rec_mut(), 3u16, 4 as u16);
6071        self.as_rec_mut().extend(value.to_be_bytes());
6072        self
6073    }
6074    pub fn push_mark(mut self, value: u32) -> Self {
6075        push_header(self.as_rec_mut(), 8u16, 4 as u16);
6076        self.as_rec_mut().extend(value.to_be_bytes());
6077        self
6078    }
6079    #[doc = "conntrack zone id"]
6080    pub fn push_zone(mut self, value: u16) -> Self {
6081        push_header(self.as_rec_mut(), 18u16, 2 as u16);
6082        self.as_rec_mut().extend(value.to_be_bytes());
6083        self
6084    }
6085    pub fn nested_filter(mut self) -> PushTupleAttrs<Self> {
6086        let header_offset = push_nested_header(self.as_rec_mut(), 25u16);
6087        PushTupleAttrs {
6088            prev: Some(self),
6089            header_offset: Some(header_offset),
6090        }
6091    }
6092}
6093impl<Prev: Rec> Drop for PushOpGetDumpRequest<Prev> {
6094    fn drop(&mut self) {
6095        if let Some(prev) = &mut self.prev {
6096            if let Some(header_offset) = &self.header_offset {
6097                finalize_nested_header(prev.as_rec_mut(), *header_offset);
6098            }
6099        }
6100    }
6101}
6102#[doc = "get / dump entries"]
6103#[derive(Clone)]
6104pub enum OpGetDumpRequest<'a> {
6105    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6106    Status(u32),
6107    Mark(u32),
6108    #[doc = "conntrack zone id"]
6109    Zone(u16),
6110    Filter(IterableTupleAttrs<'a>),
6111}
6112impl<'a> IterableOpGetDumpRequest<'a> {
6113    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6114    pub fn get_status(&self) -> Result<u32, ErrorContext> {
6115        let mut iter = self.clone();
6116        iter.pos = 0;
6117        for attr in iter {
6118            if let OpGetDumpRequest::Status(val) = attr? {
6119                return Ok(val);
6120            }
6121        }
6122        Err(ErrorContext::new_missing(
6123            "OpGetDumpRequest",
6124            "Status",
6125            self.orig_loc,
6126            self.buf.as_ptr() as usize,
6127        ))
6128    }
6129    pub fn get_mark(&self) -> Result<u32, ErrorContext> {
6130        let mut iter = self.clone();
6131        iter.pos = 0;
6132        for attr in iter {
6133            if let OpGetDumpRequest::Mark(val) = attr? {
6134                return Ok(val);
6135            }
6136        }
6137        Err(ErrorContext::new_missing(
6138            "OpGetDumpRequest",
6139            "Mark",
6140            self.orig_loc,
6141            self.buf.as_ptr() as usize,
6142        ))
6143    }
6144    #[doc = "conntrack zone id"]
6145    pub fn get_zone(&self) -> Result<u16, ErrorContext> {
6146        let mut iter = self.clone();
6147        iter.pos = 0;
6148        for attr in iter {
6149            if let OpGetDumpRequest::Zone(val) = attr? {
6150                return Ok(val);
6151            }
6152        }
6153        Err(ErrorContext::new_missing(
6154            "OpGetDumpRequest",
6155            "Zone",
6156            self.orig_loc,
6157            self.buf.as_ptr() as usize,
6158        ))
6159    }
6160    pub fn get_filter(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
6161        let mut iter = self.clone();
6162        iter.pos = 0;
6163        for attr in iter {
6164            if let OpGetDumpRequest::Filter(val) = attr? {
6165                return Ok(val);
6166            }
6167        }
6168        Err(ErrorContext::new_missing(
6169            "OpGetDumpRequest",
6170            "Filter",
6171            self.orig_loc,
6172            self.buf.as_ptr() as usize,
6173        ))
6174    }
6175}
6176impl OpGetDumpRequest<'_> {
6177    pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetDumpRequest<'a>) {
6178        let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
6179        (
6180            PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
6181            IterableOpGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize),
6182        )
6183    }
6184    fn attr_from_type(r#type: u16) -> Option<&'static str> {
6185        ConntrackAttrs::attr_from_type(r#type)
6186    }
6187}
6188#[derive(Clone, Copy, Default)]
6189pub struct IterableOpGetDumpRequest<'a> {
6190    buf: &'a [u8],
6191    pos: usize,
6192    orig_loc: usize,
6193}
6194impl<'a> IterableOpGetDumpRequest<'a> {
6195    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6196        Self {
6197            buf,
6198            pos: 0,
6199            orig_loc,
6200        }
6201    }
6202    pub fn get_buf(&self) -> &'a [u8] {
6203        self.buf
6204    }
6205}
6206impl<'a> Iterator for IterableOpGetDumpRequest<'a> {
6207    type Item = Result<OpGetDumpRequest<'a>, ErrorContext>;
6208    fn next(&mut self) -> Option<Self::Item> {
6209        let pos = self.pos;
6210        let mut r#type;
6211        loop {
6212            r#type = None;
6213            if self.buf.len() == self.pos {
6214                return None;
6215            }
6216            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6217                break;
6218            };
6219            r#type = Some(header.r#type);
6220            let res = match header.r#type {
6221                3u16 => OpGetDumpRequest::Status({
6222                    let res = parse_be_u32(next);
6223                    let Some(val) = res else { break };
6224                    val
6225                }),
6226                8u16 => OpGetDumpRequest::Mark({
6227                    let res = parse_be_u32(next);
6228                    let Some(val) = res else { break };
6229                    val
6230                }),
6231                18u16 => OpGetDumpRequest::Zone({
6232                    let res = parse_be_u16(next);
6233                    let Some(val) = res else { break };
6234                    val
6235                }),
6236                25u16 => OpGetDumpRequest::Filter({
6237                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
6238                    let Some(val) = res else { break };
6239                    val
6240                }),
6241                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6242                n => continue,
6243            };
6244            return Some(Ok(res));
6245        }
6246        Some(Err(ErrorContext::new(
6247            "OpGetDumpRequest",
6248            r#type.and_then(|t| OpGetDumpRequest::attr_from_type(t)),
6249            self.orig_loc,
6250            self.buf.as_ptr().wrapping_add(pos) as usize,
6251        )))
6252    }
6253}
6254impl<'a> std::fmt::Debug for IterableOpGetDumpRequest<'_> {
6255    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6256        let mut fmt = f.debug_struct("OpGetDumpRequest");
6257        for attr in self.clone() {
6258            let attr = match attr {
6259                Ok(a) => a,
6260                Err(err) => {
6261                    fmt.finish()?;
6262                    f.write_str("Err(")?;
6263                    err.fmt(f)?;
6264                    return f.write_str(")");
6265                }
6266            };
6267            match attr {
6268                OpGetDumpRequest::Status(val) => {
6269                    fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
6270                }
6271                OpGetDumpRequest::Mark(val) => fmt.field("Mark", &val),
6272                OpGetDumpRequest::Zone(val) => fmt.field("Zone", &val),
6273                OpGetDumpRequest::Filter(val) => fmt.field("Filter", &val),
6274            };
6275        }
6276        fmt.finish()
6277    }
6278}
6279impl IterableOpGetDumpRequest<'_> {
6280    pub fn lookup_attr(
6281        &self,
6282        offset: usize,
6283        missing_type: Option<u16>,
6284    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6285        let mut stack = Vec::new();
6286        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6287        if cur == offset + PushNfgenmsg::len() {
6288            stack.push(("OpGetDumpRequest", offset));
6289            return (
6290                stack,
6291                missing_type.and_then(|t| OpGetDumpRequest::attr_from_type(t)),
6292            );
6293        }
6294        if cur > offset || cur + self.buf.len() < offset {
6295            return (stack, None);
6296        }
6297        let mut attrs = self.clone();
6298        let mut last_off = cur + attrs.pos;
6299        let mut missing = None;
6300        while let Some(attr) = attrs.next() {
6301            let Ok(attr) = attr else { break };
6302            match attr {
6303                OpGetDumpRequest::Status(val) => {
6304                    if last_off == offset {
6305                        stack.push(("Status", last_off));
6306                        break;
6307                    }
6308                }
6309                OpGetDumpRequest::Mark(val) => {
6310                    if last_off == offset {
6311                        stack.push(("Mark", last_off));
6312                        break;
6313                    }
6314                }
6315                OpGetDumpRequest::Zone(val) => {
6316                    if last_off == offset {
6317                        stack.push(("Zone", last_off));
6318                        break;
6319                    }
6320                }
6321                OpGetDumpRequest::Filter(val) => {
6322                    (stack, missing) = val.lookup_attr(offset, missing_type);
6323                    if !stack.is_empty() {
6324                        break;
6325                    }
6326                }
6327                _ => {}
6328            };
6329            last_off = cur + attrs.pos;
6330        }
6331        if !stack.is_empty() {
6332            stack.push(("OpGetDumpRequest", cur));
6333        }
6334        (stack, missing)
6335    }
6336}
6337#[doc = "get / dump entries"]
6338pub struct PushOpGetDumpReply<Prev: Rec> {
6339    pub(crate) prev: Option<Prev>,
6340    pub(crate) header_offset: Option<usize>,
6341}
6342impl<Prev: Rec> Rec for PushOpGetDumpReply<Prev> {
6343    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6344        self.prev.as_mut().unwrap().as_rec_mut()
6345    }
6346    fn as_rec(&self) -> &Vec<u8> {
6347        self.prev.as_ref().unwrap().as_rec()
6348    }
6349}
6350impl<Prev: Rec> PushOpGetDumpReply<Prev> {
6351    pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
6352        Self::write_header(&mut prev, header);
6353        Self::new_without_header(prev)
6354    }
6355    fn new_without_header(prev: Prev) -> Self {
6356        Self {
6357            prev: Some(prev),
6358            header_offset: None,
6359        }
6360    }
6361    fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
6362        prev.as_rec_mut().extend(header.as_slice());
6363    }
6364    pub fn end_nested(mut self) -> Prev {
6365        let mut prev = self.prev.take().unwrap();
6366        if let Some(header_offset) = &self.header_offset {
6367            finalize_nested_header(prev.as_rec_mut(), *header_offset);
6368        }
6369        prev
6370    }
6371    #[doc = "conntrack l3+l4 protocol information, original direction"]
6372    pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
6373        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
6374        PushTupleAttrs {
6375            prev: Some(self),
6376            header_offset: Some(header_offset),
6377        }
6378    }
6379    #[doc = "conntrack l3+l4 protocol information, reply direction"]
6380    pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
6381        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
6382        PushTupleAttrs {
6383            prev: Some(self),
6384            header_offset: Some(header_offset),
6385        }
6386    }
6387    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6388    pub fn push_status(mut self, value: u32) -> Self {
6389        push_header(self.as_rec_mut(), 3u16, 4 as u16);
6390        self.as_rec_mut().extend(value.to_be_bytes());
6391        self
6392    }
6393    pub fn nested_protoinfo(mut self) -> PushProtoinfoAttrs<Self> {
6394        let header_offset = push_nested_header(self.as_rec_mut(), 4u16);
6395        PushProtoinfoAttrs {
6396            prev: Some(self),
6397            header_offset: Some(header_offset),
6398        }
6399    }
6400    pub fn nested_help(mut self) -> PushHelpAttrs<Self> {
6401        let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
6402        PushHelpAttrs {
6403            prev: Some(self),
6404            header_offset: Some(header_offset),
6405        }
6406    }
6407    pub fn nested_nat_src(mut self) -> PushNatAttrs<Self> {
6408        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
6409        PushNatAttrs {
6410            prev: Some(self),
6411            header_offset: Some(header_offset),
6412        }
6413    }
6414    pub fn push_timeout(mut self, value: u32) -> Self {
6415        push_header(self.as_rec_mut(), 7u16, 4 as u16);
6416        self.as_rec_mut().extend(value.to_be_bytes());
6417        self
6418    }
6419    pub fn push_mark(mut self, value: u32) -> Self {
6420        push_header(self.as_rec_mut(), 8u16, 4 as u16);
6421        self.as_rec_mut().extend(value.to_be_bytes());
6422        self
6423    }
6424    pub fn nested_counters_orig(mut self) -> PushCounterAttrs<Self> {
6425        let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
6426        PushCounterAttrs {
6427            prev: Some(self),
6428            header_offset: Some(header_offset),
6429        }
6430    }
6431    pub fn nested_counters_reply(mut self) -> PushCounterAttrs<Self> {
6432        let header_offset = push_nested_header(self.as_rec_mut(), 10u16);
6433        PushCounterAttrs {
6434            prev: Some(self),
6435            header_offset: Some(header_offset),
6436        }
6437    }
6438    pub fn push_use(mut self, value: u32) -> Self {
6439        push_header(self.as_rec_mut(), 11u16, 4 as u16);
6440        self.as_rec_mut().extend(value.to_be_bytes());
6441        self
6442    }
6443    pub fn push_id(mut self, value: u32) -> Self {
6444        push_header(self.as_rec_mut(), 12u16, 4 as u16);
6445        self.as_rec_mut().extend(value.to_be_bytes());
6446        self
6447    }
6448    pub fn nested_nat_dst(mut self) -> PushNatAttrs<Self> {
6449        let header_offset = push_nested_header(self.as_rec_mut(), 13u16);
6450        PushNatAttrs {
6451            prev: Some(self),
6452            header_offset: Some(header_offset),
6453        }
6454    }
6455    pub fn nested_tuple_master(mut self) -> PushTupleAttrs<Self> {
6456        let header_offset = push_nested_header(self.as_rec_mut(), 14u16);
6457        PushTupleAttrs {
6458            prev: Some(self),
6459            header_offset: Some(header_offset),
6460        }
6461    }
6462    pub fn nested_seq_adj_orig(mut self) -> PushSeqadjAttrs<Self> {
6463        let header_offset = push_nested_header(self.as_rec_mut(), 15u16);
6464        PushSeqadjAttrs {
6465            prev: Some(self),
6466            header_offset: Some(header_offset),
6467        }
6468    }
6469    pub fn nested_seq_adj_reply(mut self) -> PushSeqadjAttrs<Self> {
6470        let header_offset = push_nested_header(self.as_rec_mut(), 16u16);
6471        PushSeqadjAttrs {
6472            prev: Some(self),
6473            header_offset: Some(header_offset),
6474        }
6475    }
6476    #[doc = "conntrack zone id"]
6477    pub fn push_zone(mut self, value: u16) -> Self {
6478        push_header(self.as_rec_mut(), 18u16, 2 as u16);
6479        self.as_rec_mut().extend(value.to_be_bytes());
6480        self
6481    }
6482    pub fn nested_secctx(mut self) -> PushSecctxAttrs<Self> {
6483        let header_offset = push_nested_header(self.as_rec_mut(), 19u16);
6484        PushSecctxAttrs {
6485            prev: Some(self),
6486            header_offset: Some(header_offset),
6487        }
6488    }
6489    pub fn push_labels(mut self, value: &[u8]) -> Self {
6490        push_header(self.as_rec_mut(), 22u16, value.len() as u16);
6491        self.as_rec_mut().extend(value);
6492        self
6493    }
6494    pub fn nested_synproxy(mut self) -> PushSynproxyAttrs<Self> {
6495        let header_offset = push_nested_header(self.as_rec_mut(), 24u16);
6496        PushSynproxyAttrs {
6497            prev: Some(self),
6498            header_offset: Some(header_offset),
6499        }
6500    }
6501}
6502impl<Prev: Rec> Drop for PushOpGetDumpReply<Prev> {
6503    fn drop(&mut self) {
6504        if let Some(prev) = &mut self.prev {
6505            if let Some(header_offset) = &self.header_offset {
6506                finalize_nested_header(prev.as_rec_mut(), *header_offset);
6507            }
6508        }
6509    }
6510}
6511#[doc = "get / dump entries"]
6512#[derive(Clone)]
6513pub enum OpGetDumpReply<'a> {
6514    #[doc = "conntrack l3+l4 protocol information, original direction"]
6515    TupleOrig(IterableTupleAttrs<'a>),
6516    #[doc = "conntrack l3+l4 protocol information, reply direction"]
6517    TupleReply(IterableTupleAttrs<'a>),
6518    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6519    Status(u32),
6520    Protoinfo(IterableProtoinfoAttrs<'a>),
6521    Help(IterableHelpAttrs<'a>),
6522    NatSrc(IterableNatAttrs<'a>),
6523    Timeout(u32),
6524    Mark(u32),
6525    CountersOrig(IterableCounterAttrs<'a>),
6526    CountersReply(IterableCounterAttrs<'a>),
6527    Use(u32),
6528    Id(u32),
6529    NatDst(IterableNatAttrs<'a>),
6530    TupleMaster(IterableTupleAttrs<'a>),
6531    SeqAdjOrig(IterableSeqadjAttrs<'a>),
6532    SeqAdjReply(IterableSeqadjAttrs<'a>),
6533    #[doc = "conntrack zone id"]
6534    Zone(u16),
6535    Secctx(IterableSecctxAttrs<'a>),
6536    Labels(&'a [u8]),
6537    Synproxy(IterableSynproxyAttrs<'a>),
6538}
6539impl<'a> IterableOpGetDumpReply<'a> {
6540    #[doc = "conntrack l3+l4 protocol information, original direction"]
6541    pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
6542        let mut iter = self.clone();
6543        iter.pos = 0;
6544        for attr in iter {
6545            if let OpGetDumpReply::TupleOrig(val) = attr? {
6546                return Ok(val);
6547            }
6548        }
6549        Err(ErrorContext::new_missing(
6550            "OpGetDumpReply",
6551            "TupleOrig",
6552            self.orig_loc,
6553            self.buf.as_ptr() as usize,
6554        ))
6555    }
6556    #[doc = "conntrack l3+l4 protocol information, reply direction"]
6557    pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
6558        let mut iter = self.clone();
6559        iter.pos = 0;
6560        for attr in iter {
6561            if let OpGetDumpReply::TupleReply(val) = attr? {
6562                return Ok(val);
6563            }
6564        }
6565        Err(ErrorContext::new_missing(
6566            "OpGetDumpReply",
6567            "TupleReply",
6568            self.orig_loc,
6569            self.buf.as_ptr() as usize,
6570        ))
6571    }
6572    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6573    pub fn get_status(&self) -> Result<u32, ErrorContext> {
6574        let mut iter = self.clone();
6575        iter.pos = 0;
6576        for attr in iter {
6577            if let OpGetDumpReply::Status(val) = attr? {
6578                return Ok(val);
6579            }
6580        }
6581        Err(ErrorContext::new_missing(
6582            "OpGetDumpReply",
6583            "Status",
6584            self.orig_loc,
6585            self.buf.as_ptr() as usize,
6586        ))
6587    }
6588    pub fn get_protoinfo(&self) -> Result<IterableProtoinfoAttrs<'a>, ErrorContext> {
6589        let mut iter = self.clone();
6590        iter.pos = 0;
6591        for attr in iter {
6592            if let OpGetDumpReply::Protoinfo(val) = attr? {
6593                return Ok(val);
6594            }
6595        }
6596        Err(ErrorContext::new_missing(
6597            "OpGetDumpReply",
6598            "Protoinfo",
6599            self.orig_loc,
6600            self.buf.as_ptr() as usize,
6601        ))
6602    }
6603    pub fn get_help(&self) -> Result<IterableHelpAttrs<'a>, ErrorContext> {
6604        let mut iter = self.clone();
6605        iter.pos = 0;
6606        for attr in iter {
6607            if let OpGetDumpReply::Help(val) = attr? {
6608                return Ok(val);
6609            }
6610        }
6611        Err(ErrorContext::new_missing(
6612            "OpGetDumpReply",
6613            "Help",
6614            self.orig_loc,
6615            self.buf.as_ptr() as usize,
6616        ))
6617    }
6618    pub fn get_nat_src(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
6619        let mut iter = self.clone();
6620        iter.pos = 0;
6621        for attr in iter {
6622            if let OpGetDumpReply::NatSrc(val) = attr? {
6623                return Ok(val);
6624            }
6625        }
6626        Err(ErrorContext::new_missing(
6627            "OpGetDumpReply",
6628            "NatSrc",
6629            self.orig_loc,
6630            self.buf.as_ptr() as usize,
6631        ))
6632    }
6633    pub fn get_timeout(&self) -> Result<u32, ErrorContext> {
6634        let mut iter = self.clone();
6635        iter.pos = 0;
6636        for attr in iter {
6637            if let OpGetDumpReply::Timeout(val) = attr? {
6638                return Ok(val);
6639            }
6640        }
6641        Err(ErrorContext::new_missing(
6642            "OpGetDumpReply",
6643            "Timeout",
6644            self.orig_loc,
6645            self.buf.as_ptr() as usize,
6646        ))
6647    }
6648    pub fn get_mark(&self) -> Result<u32, ErrorContext> {
6649        let mut iter = self.clone();
6650        iter.pos = 0;
6651        for attr in iter {
6652            if let OpGetDumpReply::Mark(val) = attr? {
6653                return Ok(val);
6654            }
6655        }
6656        Err(ErrorContext::new_missing(
6657            "OpGetDumpReply",
6658            "Mark",
6659            self.orig_loc,
6660            self.buf.as_ptr() as usize,
6661        ))
6662    }
6663    pub fn get_counters_orig(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
6664        let mut iter = self.clone();
6665        iter.pos = 0;
6666        for attr in iter {
6667            if let OpGetDumpReply::CountersOrig(val) = attr? {
6668                return Ok(val);
6669            }
6670        }
6671        Err(ErrorContext::new_missing(
6672            "OpGetDumpReply",
6673            "CountersOrig",
6674            self.orig_loc,
6675            self.buf.as_ptr() as usize,
6676        ))
6677    }
6678    pub fn get_counters_reply(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
6679        let mut iter = self.clone();
6680        iter.pos = 0;
6681        for attr in iter {
6682            if let OpGetDumpReply::CountersReply(val) = attr? {
6683                return Ok(val);
6684            }
6685        }
6686        Err(ErrorContext::new_missing(
6687            "OpGetDumpReply",
6688            "CountersReply",
6689            self.orig_loc,
6690            self.buf.as_ptr() as usize,
6691        ))
6692    }
6693    pub fn get_use(&self) -> Result<u32, ErrorContext> {
6694        let mut iter = self.clone();
6695        iter.pos = 0;
6696        for attr in iter {
6697            if let OpGetDumpReply::Use(val) = attr? {
6698                return Ok(val);
6699            }
6700        }
6701        Err(ErrorContext::new_missing(
6702            "OpGetDumpReply",
6703            "Use",
6704            self.orig_loc,
6705            self.buf.as_ptr() as usize,
6706        ))
6707    }
6708    pub fn get_id(&self) -> Result<u32, ErrorContext> {
6709        let mut iter = self.clone();
6710        iter.pos = 0;
6711        for attr in iter {
6712            if let OpGetDumpReply::Id(val) = attr? {
6713                return Ok(val);
6714            }
6715        }
6716        Err(ErrorContext::new_missing(
6717            "OpGetDumpReply",
6718            "Id",
6719            self.orig_loc,
6720            self.buf.as_ptr() as usize,
6721        ))
6722    }
6723    pub fn get_nat_dst(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
6724        let mut iter = self.clone();
6725        iter.pos = 0;
6726        for attr in iter {
6727            if let OpGetDumpReply::NatDst(val) = attr? {
6728                return Ok(val);
6729            }
6730        }
6731        Err(ErrorContext::new_missing(
6732            "OpGetDumpReply",
6733            "NatDst",
6734            self.orig_loc,
6735            self.buf.as_ptr() as usize,
6736        ))
6737    }
6738    pub fn get_tuple_master(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
6739        let mut iter = self.clone();
6740        iter.pos = 0;
6741        for attr in iter {
6742            if let OpGetDumpReply::TupleMaster(val) = attr? {
6743                return Ok(val);
6744            }
6745        }
6746        Err(ErrorContext::new_missing(
6747            "OpGetDumpReply",
6748            "TupleMaster",
6749            self.orig_loc,
6750            self.buf.as_ptr() as usize,
6751        ))
6752    }
6753    pub fn get_seq_adj_orig(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
6754        let mut iter = self.clone();
6755        iter.pos = 0;
6756        for attr in iter {
6757            if let OpGetDumpReply::SeqAdjOrig(val) = attr? {
6758                return Ok(val);
6759            }
6760        }
6761        Err(ErrorContext::new_missing(
6762            "OpGetDumpReply",
6763            "SeqAdjOrig",
6764            self.orig_loc,
6765            self.buf.as_ptr() as usize,
6766        ))
6767    }
6768    pub fn get_seq_adj_reply(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
6769        let mut iter = self.clone();
6770        iter.pos = 0;
6771        for attr in iter {
6772            if let OpGetDumpReply::SeqAdjReply(val) = attr? {
6773                return Ok(val);
6774            }
6775        }
6776        Err(ErrorContext::new_missing(
6777            "OpGetDumpReply",
6778            "SeqAdjReply",
6779            self.orig_loc,
6780            self.buf.as_ptr() as usize,
6781        ))
6782    }
6783    #[doc = "conntrack zone id"]
6784    pub fn get_zone(&self) -> Result<u16, ErrorContext> {
6785        let mut iter = self.clone();
6786        iter.pos = 0;
6787        for attr in iter {
6788            if let OpGetDumpReply::Zone(val) = attr? {
6789                return Ok(val);
6790            }
6791        }
6792        Err(ErrorContext::new_missing(
6793            "OpGetDumpReply",
6794            "Zone",
6795            self.orig_loc,
6796            self.buf.as_ptr() as usize,
6797        ))
6798    }
6799    pub fn get_secctx(&self) -> Result<IterableSecctxAttrs<'a>, ErrorContext> {
6800        let mut iter = self.clone();
6801        iter.pos = 0;
6802        for attr in iter {
6803            if let OpGetDumpReply::Secctx(val) = attr? {
6804                return Ok(val);
6805            }
6806        }
6807        Err(ErrorContext::new_missing(
6808            "OpGetDumpReply",
6809            "Secctx",
6810            self.orig_loc,
6811            self.buf.as_ptr() as usize,
6812        ))
6813    }
6814    pub fn get_labels(&self) -> Result<&'a [u8], ErrorContext> {
6815        let mut iter = self.clone();
6816        iter.pos = 0;
6817        for attr in iter {
6818            if let OpGetDumpReply::Labels(val) = attr? {
6819                return Ok(val);
6820            }
6821        }
6822        Err(ErrorContext::new_missing(
6823            "OpGetDumpReply",
6824            "Labels",
6825            self.orig_loc,
6826            self.buf.as_ptr() as usize,
6827        ))
6828    }
6829    pub fn get_synproxy(&self) -> Result<IterableSynproxyAttrs<'a>, ErrorContext> {
6830        let mut iter = self.clone();
6831        iter.pos = 0;
6832        for attr in iter {
6833            if let OpGetDumpReply::Synproxy(val) = attr? {
6834                return Ok(val);
6835            }
6836        }
6837        Err(ErrorContext::new_missing(
6838            "OpGetDumpReply",
6839            "Synproxy",
6840            self.orig_loc,
6841            self.buf.as_ptr() as usize,
6842        ))
6843    }
6844}
6845impl OpGetDumpReply<'_> {
6846    pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetDumpReply<'a>) {
6847        let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
6848        (
6849            PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
6850            IterableOpGetDumpReply::with_loc(attrs, buf.as_ptr() as usize),
6851        )
6852    }
6853    fn attr_from_type(r#type: u16) -> Option<&'static str> {
6854        ConntrackAttrs::attr_from_type(r#type)
6855    }
6856}
6857#[derive(Clone, Copy, Default)]
6858pub struct IterableOpGetDumpReply<'a> {
6859    buf: &'a [u8],
6860    pos: usize,
6861    orig_loc: usize,
6862}
6863impl<'a> IterableOpGetDumpReply<'a> {
6864    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6865        Self {
6866            buf,
6867            pos: 0,
6868            orig_loc,
6869        }
6870    }
6871    pub fn get_buf(&self) -> &'a [u8] {
6872        self.buf
6873    }
6874}
6875impl<'a> Iterator for IterableOpGetDumpReply<'a> {
6876    type Item = Result<OpGetDumpReply<'a>, ErrorContext>;
6877    fn next(&mut self) -> Option<Self::Item> {
6878        let pos = self.pos;
6879        let mut r#type;
6880        loop {
6881            r#type = None;
6882            if self.buf.len() == self.pos {
6883                return None;
6884            }
6885            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6886                break;
6887            };
6888            r#type = Some(header.r#type);
6889            let res = match header.r#type {
6890                1u16 => OpGetDumpReply::TupleOrig({
6891                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
6892                    let Some(val) = res else { break };
6893                    val
6894                }),
6895                2u16 => OpGetDumpReply::TupleReply({
6896                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
6897                    let Some(val) = res else { break };
6898                    val
6899                }),
6900                3u16 => OpGetDumpReply::Status({
6901                    let res = parse_be_u32(next);
6902                    let Some(val) = res else { break };
6903                    val
6904                }),
6905                4u16 => OpGetDumpReply::Protoinfo({
6906                    let res = Some(IterableProtoinfoAttrs::with_loc(next, self.orig_loc));
6907                    let Some(val) = res else { break };
6908                    val
6909                }),
6910                5u16 => OpGetDumpReply::Help({
6911                    let res = Some(IterableHelpAttrs::with_loc(next, self.orig_loc));
6912                    let Some(val) = res else { break };
6913                    val
6914                }),
6915                6u16 => OpGetDumpReply::NatSrc({
6916                    let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
6917                    let Some(val) = res else { break };
6918                    val
6919                }),
6920                7u16 => OpGetDumpReply::Timeout({
6921                    let res = parse_be_u32(next);
6922                    let Some(val) = res else { break };
6923                    val
6924                }),
6925                8u16 => OpGetDumpReply::Mark({
6926                    let res = parse_be_u32(next);
6927                    let Some(val) = res else { break };
6928                    val
6929                }),
6930                9u16 => OpGetDumpReply::CountersOrig({
6931                    let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
6932                    let Some(val) = res else { break };
6933                    val
6934                }),
6935                10u16 => OpGetDumpReply::CountersReply({
6936                    let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
6937                    let Some(val) = res else { break };
6938                    val
6939                }),
6940                11u16 => OpGetDumpReply::Use({
6941                    let res = parse_be_u32(next);
6942                    let Some(val) = res else { break };
6943                    val
6944                }),
6945                12u16 => OpGetDumpReply::Id({
6946                    let res = parse_be_u32(next);
6947                    let Some(val) = res else { break };
6948                    val
6949                }),
6950                13u16 => OpGetDumpReply::NatDst({
6951                    let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
6952                    let Some(val) = res else { break };
6953                    val
6954                }),
6955                14u16 => OpGetDumpReply::TupleMaster({
6956                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
6957                    let Some(val) = res else { break };
6958                    val
6959                }),
6960                15u16 => OpGetDumpReply::SeqAdjOrig({
6961                    let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
6962                    let Some(val) = res else { break };
6963                    val
6964                }),
6965                16u16 => OpGetDumpReply::SeqAdjReply({
6966                    let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
6967                    let Some(val) = res else { break };
6968                    val
6969                }),
6970                18u16 => OpGetDumpReply::Zone({
6971                    let res = parse_be_u16(next);
6972                    let Some(val) = res else { break };
6973                    val
6974                }),
6975                19u16 => OpGetDumpReply::Secctx({
6976                    let res = Some(IterableSecctxAttrs::with_loc(next, self.orig_loc));
6977                    let Some(val) = res else { break };
6978                    val
6979                }),
6980                22u16 => OpGetDumpReply::Labels({
6981                    let res = Some(next);
6982                    let Some(val) = res else { break };
6983                    val
6984                }),
6985                24u16 => OpGetDumpReply::Synproxy({
6986                    let res = Some(IterableSynproxyAttrs::with_loc(next, self.orig_loc));
6987                    let Some(val) = res else { break };
6988                    val
6989                }),
6990                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6991                n => continue,
6992            };
6993            return Some(Ok(res));
6994        }
6995        Some(Err(ErrorContext::new(
6996            "OpGetDumpReply",
6997            r#type.and_then(|t| OpGetDumpReply::attr_from_type(t)),
6998            self.orig_loc,
6999            self.buf.as_ptr().wrapping_add(pos) as usize,
7000        )))
7001    }
7002}
7003impl<'a> std::fmt::Debug for IterableOpGetDumpReply<'_> {
7004    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7005        let mut fmt = f.debug_struct("OpGetDumpReply");
7006        for attr in self.clone() {
7007            let attr = match attr {
7008                Ok(a) => a,
7009                Err(err) => {
7010                    fmt.finish()?;
7011                    f.write_str("Err(")?;
7012                    err.fmt(f)?;
7013                    return f.write_str(")");
7014                }
7015            };
7016            match attr {
7017                OpGetDumpReply::TupleOrig(val) => fmt.field("TupleOrig", &val),
7018                OpGetDumpReply::TupleReply(val) => fmt.field("TupleReply", &val),
7019                OpGetDumpReply::Status(val) => {
7020                    fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
7021                }
7022                OpGetDumpReply::Protoinfo(val) => fmt.field("Protoinfo", &val),
7023                OpGetDumpReply::Help(val) => fmt.field("Help", &val),
7024                OpGetDumpReply::NatSrc(val) => fmt.field("NatSrc", &val),
7025                OpGetDumpReply::Timeout(val) => fmt.field("Timeout", &val),
7026                OpGetDumpReply::Mark(val) => fmt.field("Mark", &val),
7027                OpGetDumpReply::CountersOrig(val) => fmt.field("CountersOrig", &val),
7028                OpGetDumpReply::CountersReply(val) => fmt.field("CountersReply", &val),
7029                OpGetDumpReply::Use(val) => fmt.field("Use", &val),
7030                OpGetDumpReply::Id(val) => fmt.field("Id", &val),
7031                OpGetDumpReply::NatDst(val) => fmt.field("NatDst", &val),
7032                OpGetDumpReply::TupleMaster(val) => fmt.field("TupleMaster", &val),
7033                OpGetDumpReply::SeqAdjOrig(val) => fmt.field("SeqAdjOrig", &val),
7034                OpGetDumpReply::SeqAdjReply(val) => fmt.field("SeqAdjReply", &val),
7035                OpGetDumpReply::Zone(val) => fmt.field("Zone", &val),
7036                OpGetDumpReply::Secctx(val) => fmt.field("Secctx", &val),
7037                OpGetDumpReply::Labels(val) => fmt.field("Labels", &val),
7038                OpGetDumpReply::Synproxy(val) => fmt.field("Synproxy", &val),
7039            };
7040        }
7041        fmt.finish()
7042    }
7043}
7044impl IterableOpGetDumpReply<'_> {
7045    pub fn lookup_attr(
7046        &self,
7047        offset: usize,
7048        missing_type: Option<u16>,
7049    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7050        let mut stack = Vec::new();
7051        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7052        if cur == offset + PushNfgenmsg::len() {
7053            stack.push(("OpGetDumpReply", offset));
7054            return (
7055                stack,
7056                missing_type.and_then(|t| OpGetDumpReply::attr_from_type(t)),
7057            );
7058        }
7059        if cur > offset || cur + self.buf.len() < offset {
7060            return (stack, None);
7061        }
7062        let mut attrs = self.clone();
7063        let mut last_off = cur + attrs.pos;
7064        let mut missing = None;
7065        while let Some(attr) = attrs.next() {
7066            let Ok(attr) = attr else { break };
7067            match attr {
7068                OpGetDumpReply::TupleOrig(val) => {
7069                    (stack, missing) = val.lookup_attr(offset, missing_type);
7070                    if !stack.is_empty() {
7071                        break;
7072                    }
7073                }
7074                OpGetDumpReply::TupleReply(val) => {
7075                    (stack, missing) = val.lookup_attr(offset, missing_type);
7076                    if !stack.is_empty() {
7077                        break;
7078                    }
7079                }
7080                OpGetDumpReply::Status(val) => {
7081                    if last_off == offset {
7082                        stack.push(("Status", last_off));
7083                        break;
7084                    }
7085                }
7086                OpGetDumpReply::Protoinfo(val) => {
7087                    (stack, missing) = val.lookup_attr(offset, missing_type);
7088                    if !stack.is_empty() {
7089                        break;
7090                    }
7091                }
7092                OpGetDumpReply::Help(val) => {
7093                    (stack, missing) = val.lookup_attr(offset, missing_type);
7094                    if !stack.is_empty() {
7095                        break;
7096                    }
7097                }
7098                OpGetDumpReply::NatSrc(val) => {
7099                    (stack, missing) = val.lookup_attr(offset, missing_type);
7100                    if !stack.is_empty() {
7101                        break;
7102                    }
7103                }
7104                OpGetDumpReply::Timeout(val) => {
7105                    if last_off == offset {
7106                        stack.push(("Timeout", last_off));
7107                        break;
7108                    }
7109                }
7110                OpGetDumpReply::Mark(val) => {
7111                    if last_off == offset {
7112                        stack.push(("Mark", last_off));
7113                        break;
7114                    }
7115                }
7116                OpGetDumpReply::CountersOrig(val) => {
7117                    (stack, missing) = val.lookup_attr(offset, missing_type);
7118                    if !stack.is_empty() {
7119                        break;
7120                    }
7121                }
7122                OpGetDumpReply::CountersReply(val) => {
7123                    (stack, missing) = val.lookup_attr(offset, missing_type);
7124                    if !stack.is_empty() {
7125                        break;
7126                    }
7127                }
7128                OpGetDumpReply::Use(val) => {
7129                    if last_off == offset {
7130                        stack.push(("Use", last_off));
7131                        break;
7132                    }
7133                }
7134                OpGetDumpReply::Id(val) => {
7135                    if last_off == offset {
7136                        stack.push(("Id", last_off));
7137                        break;
7138                    }
7139                }
7140                OpGetDumpReply::NatDst(val) => {
7141                    (stack, missing) = val.lookup_attr(offset, missing_type);
7142                    if !stack.is_empty() {
7143                        break;
7144                    }
7145                }
7146                OpGetDumpReply::TupleMaster(val) => {
7147                    (stack, missing) = val.lookup_attr(offset, missing_type);
7148                    if !stack.is_empty() {
7149                        break;
7150                    }
7151                }
7152                OpGetDumpReply::SeqAdjOrig(val) => {
7153                    (stack, missing) = val.lookup_attr(offset, missing_type);
7154                    if !stack.is_empty() {
7155                        break;
7156                    }
7157                }
7158                OpGetDumpReply::SeqAdjReply(val) => {
7159                    (stack, missing) = val.lookup_attr(offset, missing_type);
7160                    if !stack.is_empty() {
7161                        break;
7162                    }
7163                }
7164                OpGetDumpReply::Zone(val) => {
7165                    if last_off == offset {
7166                        stack.push(("Zone", last_off));
7167                        break;
7168                    }
7169                }
7170                OpGetDumpReply::Secctx(val) => {
7171                    (stack, missing) = val.lookup_attr(offset, missing_type);
7172                    if !stack.is_empty() {
7173                        break;
7174                    }
7175                }
7176                OpGetDumpReply::Labels(val) => {
7177                    if last_off == offset {
7178                        stack.push(("Labels", last_off));
7179                        break;
7180                    }
7181                }
7182                OpGetDumpReply::Synproxy(val) => {
7183                    (stack, missing) = val.lookup_attr(offset, missing_type);
7184                    if !stack.is_empty() {
7185                        break;
7186                    }
7187                }
7188                _ => {}
7189            };
7190            last_off = cur + attrs.pos;
7191        }
7192        if !stack.is_empty() {
7193            stack.push(("OpGetDumpReply", cur));
7194        }
7195        (stack, missing)
7196    }
7197}
7198#[derive(Debug)]
7199pub struct RequestOpGetDumpRequest<'r> {
7200    request: Request<'r>,
7201}
7202impl<'r> RequestOpGetDumpRequest<'r> {
7203    pub fn new(mut request: Request<'r>, header: &PushNfgenmsg) -> Self {
7204        PushOpGetDumpRequest::write_header(&mut request.buf_mut(), header);
7205        Self {
7206            request: request.set_dump(),
7207        }
7208    }
7209    pub fn encode(&mut self) -> PushOpGetDumpRequest<&mut Vec<u8>> {
7210        PushOpGetDumpRequest::new_without_header(self.request.buf_mut())
7211    }
7212    pub fn into_encoder(self) -> PushOpGetDumpRequest<RequestBuf<'r>> {
7213        PushOpGetDumpRequest::new_without_header(self.request.buf)
7214    }
7215    pub fn decode_request<'buf>(buf: &'buf [u8]) -> (PushNfgenmsg, IterableOpGetDumpRequest<'buf>) {
7216        OpGetDumpRequest::new(buf)
7217    }
7218}
7219impl NetlinkRequest for RequestOpGetDumpRequest<'_> {
7220    fn protocol(&self) -> Protocol {
7221        Protocol::Raw {
7222            protonum: 12u16,
7223            request_type: 257u16,
7224        }
7225    }
7226    fn flags(&self) -> u16 {
7227        self.request.flags
7228    }
7229    fn payload(&self) -> &[u8] {
7230        self.request.buf()
7231    }
7232    type ReplyType<'buf> = (PushNfgenmsg, IterableOpGetDumpReply<'buf>);
7233    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7234        OpGetDumpReply::new(buf)
7235    }
7236    fn lookup(
7237        buf: &[u8],
7238        offset: usize,
7239        missing_type: Option<u16>,
7240    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7241        OpGetDumpRequest::new(buf)
7242            .1
7243            .lookup_attr(offset, missing_type)
7244    }
7245}
7246#[doc = "get / dump entries"]
7247pub struct PushOpGetDoRequest<Prev: Rec> {
7248    pub(crate) prev: Option<Prev>,
7249    pub(crate) header_offset: Option<usize>,
7250}
7251impl<Prev: Rec> Rec for PushOpGetDoRequest<Prev> {
7252    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7253        self.prev.as_mut().unwrap().as_rec_mut()
7254    }
7255    fn as_rec(&self) -> &Vec<u8> {
7256        self.prev.as_ref().unwrap().as_rec()
7257    }
7258}
7259impl<Prev: Rec> PushOpGetDoRequest<Prev> {
7260    pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
7261        Self::write_header(&mut prev, header);
7262        Self::new_without_header(prev)
7263    }
7264    fn new_without_header(prev: Prev) -> Self {
7265        Self {
7266            prev: Some(prev),
7267            header_offset: None,
7268        }
7269    }
7270    fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
7271        prev.as_rec_mut().extend(header.as_slice());
7272    }
7273    pub fn end_nested(mut self) -> Prev {
7274        let mut prev = self.prev.take().unwrap();
7275        if let Some(header_offset) = &self.header_offset {
7276            finalize_nested_header(prev.as_rec_mut(), *header_offset);
7277        }
7278        prev
7279    }
7280    #[doc = "conntrack l3+l4 protocol information, original direction"]
7281    pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
7282        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7283        PushTupleAttrs {
7284            prev: Some(self),
7285            header_offset: Some(header_offset),
7286        }
7287    }
7288    #[doc = "conntrack l3+l4 protocol information, reply direction"]
7289    pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
7290        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
7291        PushTupleAttrs {
7292            prev: Some(self),
7293            header_offset: Some(header_offset),
7294        }
7295    }
7296    #[doc = "conntrack zone id"]
7297    pub fn push_zone(mut self, value: u16) -> Self {
7298        push_header(self.as_rec_mut(), 18u16, 2 as u16);
7299        self.as_rec_mut().extend(value.to_be_bytes());
7300        self
7301    }
7302}
7303impl<Prev: Rec> Drop for PushOpGetDoRequest<Prev> {
7304    fn drop(&mut self) {
7305        if let Some(prev) = &mut self.prev {
7306            if let Some(header_offset) = &self.header_offset {
7307                finalize_nested_header(prev.as_rec_mut(), *header_offset);
7308            }
7309        }
7310    }
7311}
7312#[doc = "get / dump entries"]
7313#[derive(Clone)]
7314pub enum OpGetDoRequest<'a> {
7315    #[doc = "conntrack l3+l4 protocol information, original direction"]
7316    TupleOrig(IterableTupleAttrs<'a>),
7317    #[doc = "conntrack l3+l4 protocol information, reply direction"]
7318    TupleReply(IterableTupleAttrs<'a>),
7319    #[doc = "conntrack zone id"]
7320    Zone(u16),
7321}
7322impl<'a> IterableOpGetDoRequest<'a> {
7323    #[doc = "conntrack l3+l4 protocol information, original direction"]
7324    pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7325        let mut iter = self.clone();
7326        iter.pos = 0;
7327        for attr in iter {
7328            if let OpGetDoRequest::TupleOrig(val) = attr? {
7329                return Ok(val);
7330            }
7331        }
7332        Err(ErrorContext::new_missing(
7333            "OpGetDoRequest",
7334            "TupleOrig",
7335            self.orig_loc,
7336            self.buf.as_ptr() as usize,
7337        ))
7338    }
7339    #[doc = "conntrack l3+l4 protocol information, reply direction"]
7340    pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7341        let mut iter = self.clone();
7342        iter.pos = 0;
7343        for attr in iter {
7344            if let OpGetDoRequest::TupleReply(val) = attr? {
7345                return Ok(val);
7346            }
7347        }
7348        Err(ErrorContext::new_missing(
7349            "OpGetDoRequest",
7350            "TupleReply",
7351            self.orig_loc,
7352            self.buf.as_ptr() as usize,
7353        ))
7354    }
7355    #[doc = "conntrack zone id"]
7356    pub fn get_zone(&self) -> Result<u16, ErrorContext> {
7357        let mut iter = self.clone();
7358        iter.pos = 0;
7359        for attr in iter {
7360            if let OpGetDoRequest::Zone(val) = attr? {
7361                return Ok(val);
7362            }
7363        }
7364        Err(ErrorContext::new_missing(
7365            "OpGetDoRequest",
7366            "Zone",
7367            self.orig_loc,
7368            self.buf.as_ptr() as usize,
7369        ))
7370    }
7371}
7372impl OpGetDoRequest<'_> {
7373    pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetDoRequest<'a>) {
7374        let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
7375        (
7376            PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
7377            IterableOpGetDoRequest::with_loc(attrs, buf.as_ptr() as usize),
7378        )
7379    }
7380    fn attr_from_type(r#type: u16) -> Option<&'static str> {
7381        ConntrackAttrs::attr_from_type(r#type)
7382    }
7383}
7384#[derive(Clone, Copy, Default)]
7385pub struct IterableOpGetDoRequest<'a> {
7386    buf: &'a [u8],
7387    pos: usize,
7388    orig_loc: usize,
7389}
7390impl<'a> IterableOpGetDoRequest<'a> {
7391    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7392        Self {
7393            buf,
7394            pos: 0,
7395            orig_loc,
7396        }
7397    }
7398    pub fn get_buf(&self) -> &'a [u8] {
7399        self.buf
7400    }
7401}
7402impl<'a> Iterator for IterableOpGetDoRequest<'a> {
7403    type Item = Result<OpGetDoRequest<'a>, ErrorContext>;
7404    fn next(&mut self) -> Option<Self::Item> {
7405        let pos = self.pos;
7406        let mut r#type;
7407        loop {
7408            r#type = None;
7409            if self.buf.len() == self.pos {
7410                return None;
7411            }
7412            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
7413                break;
7414            };
7415            r#type = Some(header.r#type);
7416            let res = match header.r#type {
7417                1u16 => OpGetDoRequest::TupleOrig({
7418                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
7419                    let Some(val) = res else { break };
7420                    val
7421                }),
7422                2u16 => OpGetDoRequest::TupleReply({
7423                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
7424                    let Some(val) = res else { break };
7425                    val
7426                }),
7427                18u16 => OpGetDoRequest::Zone({
7428                    let res = parse_be_u16(next);
7429                    let Some(val) = res else { break };
7430                    val
7431                }),
7432                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
7433                n => continue,
7434            };
7435            return Some(Ok(res));
7436        }
7437        Some(Err(ErrorContext::new(
7438            "OpGetDoRequest",
7439            r#type.and_then(|t| OpGetDoRequest::attr_from_type(t)),
7440            self.orig_loc,
7441            self.buf.as_ptr().wrapping_add(pos) as usize,
7442        )))
7443    }
7444}
7445impl<'a> std::fmt::Debug for IterableOpGetDoRequest<'_> {
7446    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7447        let mut fmt = f.debug_struct("OpGetDoRequest");
7448        for attr in self.clone() {
7449            let attr = match attr {
7450                Ok(a) => a,
7451                Err(err) => {
7452                    fmt.finish()?;
7453                    f.write_str("Err(")?;
7454                    err.fmt(f)?;
7455                    return f.write_str(")");
7456                }
7457            };
7458            match attr {
7459                OpGetDoRequest::TupleOrig(val) => fmt.field("TupleOrig", &val),
7460                OpGetDoRequest::TupleReply(val) => fmt.field("TupleReply", &val),
7461                OpGetDoRequest::Zone(val) => fmt.field("Zone", &val),
7462            };
7463        }
7464        fmt.finish()
7465    }
7466}
7467impl IterableOpGetDoRequest<'_> {
7468    pub fn lookup_attr(
7469        &self,
7470        offset: usize,
7471        missing_type: Option<u16>,
7472    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7473        let mut stack = Vec::new();
7474        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7475        if cur == offset + PushNfgenmsg::len() {
7476            stack.push(("OpGetDoRequest", offset));
7477            return (
7478                stack,
7479                missing_type.and_then(|t| OpGetDoRequest::attr_from_type(t)),
7480            );
7481        }
7482        if cur > offset || cur + self.buf.len() < offset {
7483            return (stack, None);
7484        }
7485        let mut attrs = self.clone();
7486        let mut last_off = cur + attrs.pos;
7487        let mut missing = None;
7488        while let Some(attr) = attrs.next() {
7489            let Ok(attr) = attr else { break };
7490            match attr {
7491                OpGetDoRequest::TupleOrig(val) => {
7492                    (stack, missing) = val.lookup_attr(offset, missing_type);
7493                    if !stack.is_empty() {
7494                        break;
7495                    }
7496                }
7497                OpGetDoRequest::TupleReply(val) => {
7498                    (stack, missing) = val.lookup_attr(offset, missing_type);
7499                    if !stack.is_empty() {
7500                        break;
7501                    }
7502                }
7503                OpGetDoRequest::Zone(val) => {
7504                    if last_off == offset {
7505                        stack.push(("Zone", last_off));
7506                        break;
7507                    }
7508                }
7509                _ => {}
7510            };
7511            last_off = cur + attrs.pos;
7512        }
7513        if !stack.is_empty() {
7514            stack.push(("OpGetDoRequest", cur));
7515        }
7516        (stack, missing)
7517    }
7518}
7519#[doc = "get / dump entries"]
7520pub struct PushOpGetDoReply<Prev: Rec> {
7521    pub(crate) prev: Option<Prev>,
7522    pub(crate) header_offset: Option<usize>,
7523}
7524impl<Prev: Rec> Rec for PushOpGetDoReply<Prev> {
7525    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7526        self.prev.as_mut().unwrap().as_rec_mut()
7527    }
7528    fn as_rec(&self) -> &Vec<u8> {
7529        self.prev.as_ref().unwrap().as_rec()
7530    }
7531}
7532impl<Prev: Rec> PushOpGetDoReply<Prev> {
7533    pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
7534        Self::write_header(&mut prev, header);
7535        Self::new_without_header(prev)
7536    }
7537    fn new_without_header(prev: Prev) -> Self {
7538        Self {
7539            prev: Some(prev),
7540            header_offset: None,
7541        }
7542    }
7543    fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
7544        prev.as_rec_mut().extend(header.as_slice());
7545    }
7546    pub fn end_nested(mut self) -> Prev {
7547        let mut prev = self.prev.take().unwrap();
7548        if let Some(header_offset) = &self.header_offset {
7549            finalize_nested_header(prev.as_rec_mut(), *header_offset);
7550        }
7551        prev
7552    }
7553    #[doc = "conntrack l3+l4 protocol information, original direction"]
7554    pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
7555        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7556        PushTupleAttrs {
7557            prev: Some(self),
7558            header_offset: Some(header_offset),
7559        }
7560    }
7561    #[doc = "conntrack l3+l4 protocol information, reply direction"]
7562    pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
7563        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
7564        PushTupleAttrs {
7565            prev: Some(self),
7566            header_offset: Some(header_offset),
7567        }
7568    }
7569    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
7570    pub fn push_status(mut self, value: u32) -> Self {
7571        push_header(self.as_rec_mut(), 3u16, 4 as u16);
7572        self.as_rec_mut().extend(value.to_be_bytes());
7573        self
7574    }
7575    pub fn nested_protoinfo(mut self) -> PushProtoinfoAttrs<Self> {
7576        let header_offset = push_nested_header(self.as_rec_mut(), 4u16);
7577        PushProtoinfoAttrs {
7578            prev: Some(self),
7579            header_offset: Some(header_offset),
7580        }
7581    }
7582    pub fn nested_help(mut self) -> PushHelpAttrs<Self> {
7583        let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
7584        PushHelpAttrs {
7585            prev: Some(self),
7586            header_offset: Some(header_offset),
7587        }
7588    }
7589    pub fn nested_nat_src(mut self) -> PushNatAttrs<Self> {
7590        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
7591        PushNatAttrs {
7592            prev: Some(self),
7593            header_offset: Some(header_offset),
7594        }
7595    }
7596    pub fn push_timeout(mut self, value: u32) -> Self {
7597        push_header(self.as_rec_mut(), 7u16, 4 as u16);
7598        self.as_rec_mut().extend(value.to_be_bytes());
7599        self
7600    }
7601    pub fn push_mark(mut self, value: u32) -> Self {
7602        push_header(self.as_rec_mut(), 8u16, 4 as u16);
7603        self.as_rec_mut().extend(value.to_be_bytes());
7604        self
7605    }
7606    pub fn nested_counters_orig(mut self) -> PushCounterAttrs<Self> {
7607        let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
7608        PushCounterAttrs {
7609            prev: Some(self),
7610            header_offset: Some(header_offset),
7611        }
7612    }
7613    pub fn nested_counters_reply(mut self) -> PushCounterAttrs<Self> {
7614        let header_offset = push_nested_header(self.as_rec_mut(), 10u16);
7615        PushCounterAttrs {
7616            prev: Some(self),
7617            header_offset: Some(header_offset),
7618        }
7619    }
7620    pub fn push_use(mut self, value: u32) -> Self {
7621        push_header(self.as_rec_mut(), 11u16, 4 as u16);
7622        self.as_rec_mut().extend(value.to_be_bytes());
7623        self
7624    }
7625    pub fn push_id(mut self, value: u32) -> Self {
7626        push_header(self.as_rec_mut(), 12u16, 4 as u16);
7627        self.as_rec_mut().extend(value.to_be_bytes());
7628        self
7629    }
7630    pub fn nested_nat_dst(mut self) -> PushNatAttrs<Self> {
7631        let header_offset = push_nested_header(self.as_rec_mut(), 13u16);
7632        PushNatAttrs {
7633            prev: Some(self),
7634            header_offset: Some(header_offset),
7635        }
7636    }
7637    pub fn nested_tuple_master(mut self) -> PushTupleAttrs<Self> {
7638        let header_offset = push_nested_header(self.as_rec_mut(), 14u16);
7639        PushTupleAttrs {
7640            prev: Some(self),
7641            header_offset: Some(header_offset),
7642        }
7643    }
7644    pub fn nested_seq_adj_orig(mut self) -> PushSeqadjAttrs<Self> {
7645        let header_offset = push_nested_header(self.as_rec_mut(), 15u16);
7646        PushSeqadjAttrs {
7647            prev: Some(self),
7648            header_offset: Some(header_offset),
7649        }
7650    }
7651    pub fn nested_seq_adj_reply(mut self) -> PushSeqadjAttrs<Self> {
7652        let header_offset = push_nested_header(self.as_rec_mut(), 16u16);
7653        PushSeqadjAttrs {
7654            prev: Some(self),
7655            header_offset: Some(header_offset),
7656        }
7657    }
7658    #[doc = "conntrack zone id"]
7659    pub fn push_zone(mut self, value: u16) -> Self {
7660        push_header(self.as_rec_mut(), 18u16, 2 as u16);
7661        self.as_rec_mut().extend(value.to_be_bytes());
7662        self
7663    }
7664    pub fn nested_secctx(mut self) -> PushSecctxAttrs<Self> {
7665        let header_offset = push_nested_header(self.as_rec_mut(), 19u16);
7666        PushSecctxAttrs {
7667            prev: Some(self),
7668            header_offset: Some(header_offset),
7669        }
7670    }
7671    pub fn push_labels(mut self, value: &[u8]) -> Self {
7672        push_header(self.as_rec_mut(), 22u16, value.len() as u16);
7673        self.as_rec_mut().extend(value);
7674        self
7675    }
7676    pub fn nested_synproxy(mut self) -> PushSynproxyAttrs<Self> {
7677        let header_offset = push_nested_header(self.as_rec_mut(), 24u16);
7678        PushSynproxyAttrs {
7679            prev: Some(self),
7680            header_offset: Some(header_offset),
7681        }
7682    }
7683}
7684impl<Prev: Rec> Drop for PushOpGetDoReply<Prev> {
7685    fn drop(&mut self) {
7686        if let Some(prev) = &mut self.prev {
7687            if let Some(header_offset) = &self.header_offset {
7688                finalize_nested_header(prev.as_rec_mut(), *header_offset);
7689            }
7690        }
7691    }
7692}
7693#[doc = "get / dump entries"]
7694#[derive(Clone)]
7695pub enum OpGetDoReply<'a> {
7696    #[doc = "conntrack l3+l4 protocol information, original direction"]
7697    TupleOrig(IterableTupleAttrs<'a>),
7698    #[doc = "conntrack l3+l4 protocol information, reply direction"]
7699    TupleReply(IterableTupleAttrs<'a>),
7700    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
7701    Status(u32),
7702    Protoinfo(IterableProtoinfoAttrs<'a>),
7703    Help(IterableHelpAttrs<'a>),
7704    NatSrc(IterableNatAttrs<'a>),
7705    Timeout(u32),
7706    Mark(u32),
7707    CountersOrig(IterableCounterAttrs<'a>),
7708    CountersReply(IterableCounterAttrs<'a>),
7709    Use(u32),
7710    Id(u32),
7711    NatDst(IterableNatAttrs<'a>),
7712    TupleMaster(IterableTupleAttrs<'a>),
7713    SeqAdjOrig(IterableSeqadjAttrs<'a>),
7714    SeqAdjReply(IterableSeqadjAttrs<'a>),
7715    #[doc = "conntrack zone id"]
7716    Zone(u16),
7717    Secctx(IterableSecctxAttrs<'a>),
7718    Labels(&'a [u8]),
7719    Synproxy(IterableSynproxyAttrs<'a>),
7720}
7721impl<'a> IterableOpGetDoReply<'a> {
7722    #[doc = "conntrack l3+l4 protocol information, original direction"]
7723    pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7724        let mut iter = self.clone();
7725        iter.pos = 0;
7726        for attr in iter {
7727            if let OpGetDoReply::TupleOrig(val) = attr? {
7728                return Ok(val);
7729            }
7730        }
7731        Err(ErrorContext::new_missing(
7732            "OpGetDoReply",
7733            "TupleOrig",
7734            self.orig_loc,
7735            self.buf.as_ptr() as usize,
7736        ))
7737    }
7738    #[doc = "conntrack l3+l4 protocol information, reply direction"]
7739    pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7740        let mut iter = self.clone();
7741        iter.pos = 0;
7742        for attr in iter {
7743            if let OpGetDoReply::TupleReply(val) = attr? {
7744                return Ok(val);
7745            }
7746        }
7747        Err(ErrorContext::new_missing(
7748            "OpGetDoReply",
7749            "TupleReply",
7750            self.orig_loc,
7751            self.buf.as_ptr() as usize,
7752        ))
7753    }
7754    #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
7755    pub fn get_status(&self) -> Result<u32, ErrorContext> {
7756        let mut iter = self.clone();
7757        iter.pos = 0;
7758        for attr in iter {
7759            if let OpGetDoReply::Status(val) = attr? {
7760                return Ok(val);
7761            }
7762        }
7763        Err(ErrorContext::new_missing(
7764            "OpGetDoReply",
7765            "Status",
7766            self.orig_loc,
7767            self.buf.as_ptr() as usize,
7768        ))
7769    }
7770    pub fn get_protoinfo(&self) -> Result<IterableProtoinfoAttrs<'a>, ErrorContext> {
7771        let mut iter = self.clone();
7772        iter.pos = 0;
7773        for attr in iter {
7774            if let OpGetDoReply::Protoinfo(val) = attr? {
7775                return Ok(val);
7776            }
7777        }
7778        Err(ErrorContext::new_missing(
7779            "OpGetDoReply",
7780            "Protoinfo",
7781            self.orig_loc,
7782            self.buf.as_ptr() as usize,
7783        ))
7784    }
7785    pub fn get_help(&self) -> Result<IterableHelpAttrs<'a>, ErrorContext> {
7786        let mut iter = self.clone();
7787        iter.pos = 0;
7788        for attr in iter {
7789            if let OpGetDoReply::Help(val) = attr? {
7790                return Ok(val);
7791            }
7792        }
7793        Err(ErrorContext::new_missing(
7794            "OpGetDoReply",
7795            "Help",
7796            self.orig_loc,
7797            self.buf.as_ptr() as usize,
7798        ))
7799    }
7800    pub fn get_nat_src(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
7801        let mut iter = self.clone();
7802        iter.pos = 0;
7803        for attr in iter {
7804            if let OpGetDoReply::NatSrc(val) = attr? {
7805                return Ok(val);
7806            }
7807        }
7808        Err(ErrorContext::new_missing(
7809            "OpGetDoReply",
7810            "NatSrc",
7811            self.orig_loc,
7812            self.buf.as_ptr() as usize,
7813        ))
7814    }
7815    pub fn get_timeout(&self) -> Result<u32, ErrorContext> {
7816        let mut iter = self.clone();
7817        iter.pos = 0;
7818        for attr in iter {
7819            if let OpGetDoReply::Timeout(val) = attr? {
7820                return Ok(val);
7821            }
7822        }
7823        Err(ErrorContext::new_missing(
7824            "OpGetDoReply",
7825            "Timeout",
7826            self.orig_loc,
7827            self.buf.as_ptr() as usize,
7828        ))
7829    }
7830    pub fn get_mark(&self) -> Result<u32, ErrorContext> {
7831        let mut iter = self.clone();
7832        iter.pos = 0;
7833        for attr in iter {
7834            if let OpGetDoReply::Mark(val) = attr? {
7835                return Ok(val);
7836            }
7837        }
7838        Err(ErrorContext::new_missing(
7839            "OpGetDoReply",
7840            "Mark",
7841            self.orig_loc,
7842            self.buf.as_ptr() as usize,
7843        ))
7844    }
7845    pub fn get_counters_orig(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
7846        let mut iter = self.clone();
7847        iter.pos = 0;
7848        for attr in iter {
7849            if let OpGetDoReply::CountersOrig(val) = attr? {
7850                return Ok(val);
7851            }
7852        }
7853        Err(ErrorContext::new_missing(
7854            "OpGetDoReply",
7855            "CountersOrig",
7856            self.orig_loc,
7857            self.buf.as_ptr() as usize,
7858        ))
7859    }
7860    pub fn get_counters_reply(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
7861        let mut iter = self.clone();
7862        iter.pos = 0;
7863        for attr in iter {
7864            if let OpGetDoReply::CountersReply(val) = attr? {
7865                return Ok(val);
7866            }
7867        }
7868        Err(ErrorContext::new_missing(
7869            "OpGetDoReply",
7870            "CountersReply",
7871            self.orig_loc,
7872            self.buf.as_ptr() as usize,
7873        ))
7874    }
7875    pub fn get_use(&self) -> Result<u32, ErrorContext> {
7876        let mut iter = self.clone();
7877        iter.pos = 0;
7878        for attr in iter {
7879            if let OpGetDoReply::Use(val) = attr? {
7880                return Ok(val);
7881            }
7882        }
7883        Err(ErrorContext::new_missing(
7884            "OpGetDoReply",
7885            "Use",
7886            self.orig_loc,
7887            self.buf.as_ptr() as usize,
7888        ))
7889    }
7890    pub fn get_id(&self) -> Result<u32, ErrorContext> {
7891        let mut iter = self.clone();
7892        iter.pos = 0;
7893        for attr in iter {
7894            if let OpGetDoReply::Id(val) = attr? {
7895                return Ok(val);
7896            }
7897        }
7898        Err(ErrorContext::new_missing(
7899            "OpGetDoReply",
7900            "Id",
7901            self.orig_loc,
7902            self.buf.as_ptr() as usize,
7903        ))
7904    }
7905    pub fn get_nat_dst(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
7906        let mut iter = self.clone();
7907        iter.pos = 0;
7908        for attr in iter {
7909            if let OpGetDoReply::NatDst(val) = attr? {
7910                return Ok(val);
7911            }
7912        }
7913        Err(ErrorContext::new_missing(
7914            "OpGetDoReply",
7915            "NatDst",
7916            self.orig_loc,
7917            self.buf.as_ptr() as usize,
7918        ))
7919    }
7920    pub fn get_tuple_master(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7921        let mut iter = self.clone();
7922        iter.pos = 0;
7923        for attr in iter {
7924            if let OpGetDoReply::TupleMaster(val) = attr? {
7925                return Ok(val);
7926            }
7927        }
7928        Err(ErrorContext::new_missing(
7929            "OpGetDoReply",
7930            "TupleMaster",
7931            self.orig_loc,
7932            self.buf.as_ptr() as usize,
7933        ))
7934    }
7935    pub fn get_seq_adj_orig(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
7936        let mut iter = self.clone();
7937        iter.pos = 0;
7938        for attr in iter {
7939            if let OpGetDoReply::SeqAdjOrig(val) = attr? {
7940                return Ok(val);
7941            }
7942        }
7943        Err(ErrorContext::new_missing(
7944            "OpGetDoReply",
7945            "SeqAdjOrig",
7946            self.orig_loc,
7947            self.buf.as_ptr() as usize,
7948        ))
7949    }
7950    pub fn get_seq_adj_reply(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
7951        let mut iter = self.clone();
7952        iter.pos = 0;
7953        for attr in iter {
7954            if let OpGetDoReply::SeqAdjReply(val) = attr? {
7955                return Ok(val);
7956            }
7957        }
7958        Err(ErrorContext::new_missing(
7959            "OpGetDoReply",
7960            "SeqAdjReply",
7961            self.orig_loc,
7962            self.buf.as_ptr() as usize,
7963        ))
7964    }
7965    #[doc = "conntrack zone id"]
7966    pub fn get_zone(&self) -> Result<u16, ErrorContext> {
7967        let mut iter = self.clone();
7968        iter.pos = 0;
7969        for attr in iter {
7970            if let OpGetDoReply::Zone(val) = attr? {
7971                return Ok(val);
7972            }
7973        }
7974        Err(ErrorContext::new_missing(
7975            "OpGetDoReply",
7976            "Zone",
7977            self.orig_loc,
7978            self.buf.as_ptr() as usize,
7979        ))
7980    }
7981    pub fn get_secctx(&self) -> Result<IterableSecctxAttrs<'a>, ErrorContext> {
7982        let mut iter = self.clone();
7983        iter.pos = 0;
7984        for attr in iter {
7985            if let OpGetDoReply::Secctx(val) = attr? {
7986                return Ok(val);
7987            }
7988        }
7989        Err(ErrorContext::new_missing(
7990            "OpGetDoReply",
7991            "Secctx",
7992            self.orig_loc,
7993            self.buf.as_ptr() as usize,
7994        ))
7995    }
7996    pub fn get_labels(&self) -> Result<&'a [u8], ErrorContext> {
7997        let mut iter = self.clone();
7998        iter.pos = 0;
7999        for attr in iter {
8000            if let OpGetDoReply::Labels(val) = attr? {
8001                return Ok(val);
8002            }
8003        }
8004        Err(ErrorContext::new_missing(
8005            "OpGetDoReply",
8006            "Labels",
8007            self.orig_loc,
8008            self.buf.as_ptr() as usize,
8009        ))
8010    }
8011    pub fn get_synproxy(&self) -> Result<IterableSynproxyAttrs<'a>, ErrorContext> {
8012        let mut iter = self.clone();
8013        iter.pos = 0;
8014        for attr in iter {
8015            if let OpGetDoReply::Synproxy(val) = attr? {
8016                return Ok(val);
8017            }
8018        }
8019        Err(ErrorContext::new_missing(
8020            "OpGetDoReply",
8021            "Synproxy",
8022            self.orig_loc,
8023            self.buf.as_ptr() as usize,
8024        ))
8025    }
8026}
8027impl OpGetDoReply<'_> {
8028    pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetDoReply<'a>) {
8029        let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
8030        (
8031            PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
8032            IterableOpGetDoReply::with_loc(attrs, buf.as_ptr() as usize),
8033        )
8034    }
8035    fn attr_from_type(r#type: u16) -> Option<&'static str> {
8036        ConntrackAttrs::attr_from_type(r#type)
8037    }
8038}
8039#[derive(Clone, Copy, Default)]
8040pub struct IterableOpGetDoReply<'a> {
8041    buf: &'a [u8],
8042    pos: usize,
8043    orig_loc: usize,
8044}
8045impl<'a> IterableOpGetDoReply<'a> {
8046    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8047        Self {
8048            buf,
8049            pos: 0,
8050            orig_loc,
8051        }
8052    }
8053    pub fn get_buf(&self) -> &'a [u8] {
8054        self.buf
8055    }
8056}
8057impl<'a> Iterator for IterableOpGetDoReply<'a> {
8058    type Item = Result<OpGetDoReply<'a>, ErrorContext>;
8059    fn next(&mut self) -> Option<Self::Item> {
8060        let pos = self.pos;
8061        let mut r#type;
8062        loop {
8063            r#type = None;
8064            if self.buf.len() == self.pos {
8065                return None;
8066            }
8067            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8068                break;
8069            };
8070            r#type = Some(header.r#type);
8071            let res = match header.r#type {
8072                1u16 => OpGetDoReply::TupleOrig({
8073                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
8074                    let Some(val) = res else { break };
8075                    val
8076                }),
8077                2u16 => OpGetDoReply::TupleReply({
8078                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
8079                    let Some(val) = res else { break };
8080                    val
8081                }),
8082                3u16 => OpGetDoReply::Status({
8083                    let res = parse_be_u32(next);
8084                    let Some(val) = res else { break };
8085                    val
8086                }),
8087                4u16 => OpGetDoReply::Protoinfo({
8088                    let res = Some(IterableProtoinfoAttrs::with_loc(next, self.orig_loc));
8089                    let Some(val) = res else { break };
8090                    val
8091                }),
8092                5u16 => OpGetDoReply::Help({
8093                    let res = Some(IterableHelpAttrs::with_loc(next, self.orig_loc));
8094                    let Some(val) = res else { break };
8095                    val
8096                }),
8097                6u16 => OpGetDoReply::NatSrc({
8098                    let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
8099                    let Some(val) = res else { break };
8100                    val
8101                }),
8102                7u16 => OpGetDoReply::Timeout({
8103                    let res = parse_be_u32(next);
8104                    let Some(val) = res else { break };
8105                    val
8106                }),
8107                8u16 => OpGetDoReply::Mark({
8108                    let res = parse_be_u32(next);
8109                    let Some(val) = res else { break };
8110                    val
8111                }),
8112                9u16 => OpGetDoReply::CountersOrig({
8113                    let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
8114                    let Some(val) = res else { break };
8115                    val
8116                }),
8117                10u16 => OpGetDoReply::CountersReply({
8118                    let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
8119                    let Some(val) = res else { break };
8120                    val
8121                }),
8122                11u16 => OpGetDoReply::Use({
8123                    let res = parse_be_u32(next);
8124                    let Some(val) = res else { break };
8125                    val
8126                }),
8127                12u16 => OpGetDoReply::Id({
8128                    let res = parse_be_u32(next);
8129                    let Some(val) = res else { break };
8130                    val
8131                }),
8132                13u16 => OpGetDoReply::NatDst({
8133                    let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
8134                    let Some(val) = res else { break };
8135                    val
8136                }),
8137                14u16 => OpGetDoReply::TupleMaster({
8138                    let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
8139                    let Some(val) = res else { break };
8140                    val
8141                }),
8142                15u16 => OpGetDoReply::SeqAdjOrig({
8143                    let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
8144                    let Some(val) = res else { break };
8145                    val
8146                }),
8147                16u16 => OpGetDoReply::SeqAdjReply({
8148                    let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
8149                    let Some(val) = res else { break };
8150                    val
8151                }),
8152                18u16 => OpGetDoReply::Zone({
8153                    let res = parse_be_u16(next);
8154                    let Some(val) = res else { break };
8155                    val
8156                }),
8157                19u16 => OpGetDoReply::Secctx({
8158                    let res = Some(IterableSecctxAttrs::with_loc(next, self.orig_loc));
8159                    let Some(val) = res else { break };
8160                    val
8161                }),
8162                22u16 => OpGetDoReply::Labels({
8163                    let res = Some(next);
8164                    let Some(val) = res else { break };
8165                    val
8166                }),
8167                24u16 => OpGetDoReply::Synproxy({
8168                    let res = Some(IterableSynproxyAttrs::with_loc(next, self.orig_loc));
8169                    let Some(val) = res else { break };
8170                    val
8171                }),
8172                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8173                n => continue,
8174            };
8175            return Some(Ok(res));
8176        }
8177        Some(Err(ErrorContext::new(
8178            "OpGetDoReply",
8179            r#type.and_then(|t| OpGetDoReply::attr_from_type(t)),
8180            self.orig_loc,
8181            self.buf.as_ptr().wrapping_add(pos) as usize,
8182        )))
8183    }
8184}
8185impl<'a> std::fmt::Debug for IterableOpGetDoReply<'_> {
8186    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8187        let mut fmt = f.debug_struct("OpGetDoReply");
8188        for attr in self.clone() {
8189            let attr = match attr {
8190                Ok(a) => a,
8191                Err(err) => {
8192                    fmt.finish()?;
8193                    f.write_str("Err(")?;
8194                    err.fmt(f)?;
8195                    return f.write_str(")");
8196                }
8197            };
8198            match attr {
8199                OpGetDoReply::TupleOrig(val) => fmt.field("TupleOrig", &val),
8200                OpGetDoReply::TupleReply(val) => fmt.field("TupleReply", &val),
8201                OpGetDoReply::Status(val) => {
8202                    fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
8203                }
8204                OpGetDoReply::Protoinfo(val) => fmt.field("Protoinfo", &val),
8205                OpGetDoReply::Help(val) => fmt.field("Help", &val),
8206                OpGetDoReply::NatSrc(val) => fmt.field("NatSrc", &val),
8207                OpGetDoReply::Timeout(val) => fmt.field("Timeout", &val),
8208                OpGetDoReply::Mark(val) => fmt.field("Mark", &val),
8209                OpGetDoReply::CountersOrig(val) => fmt.field("CountersOrig", &val),
8210                OpGetDoReply::CountersReply(val) => fmt.field("CountersReply", &val),
8211                OpGetDoReply::Use(val) => fmt.field("Use", &val),
8212                OpGetDoReply::Id(val) => fmt.field("Id", &val),
8213                OpGetDoReply::NatDst(val) => fmt.field("NatDst", &val),
8214                OpGetDoReply::TupleMaster(val) => fmt.field("TupleMaster", &val),
8215                OpGetDoReply::SeqAdjOrig(val) => fmt.field("SeqAdjOrig", &val),
8216                OpGetDoReply::SeqAdjReply(val) => fmt.field("SeqAdjReply", &val),
8217                OpGetDoReply::Zone(val) => fmt.field("Zone", &val),
8218                OpGetDoReply::Secctx(val) => fmt.field("Secctx", &val),
8219                OpGetDoReply::Labels(val) => fmt.field("Labels", &val),
8220                OpGetDoReply::Synproxy(val) => fmt.field("Synproxy", &val),
8221            };
8222        }
8223        fmt.finish()
8224    }
8225}
8226impl IterableOpGetDoReply<'_> {
8227    pub fn lookup_attr(
8228        &self,
8229        offset: usize,
8230        missing_type: Option<u16>,
8231    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8232        let mut stack = Vec::new();
8233        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8234        if cur == offset + PushNfgenmsg::len() {
8235            stack.push(("OpGetDoReply", offset));
8236            return (
8237                stack,
8238                missing_type.and_then(|t| OpGetDoReply::attr_from_type(t)),
8239            );
8240        }
8241        if cur > offset || cur + self.buf.len() < offset {
8242            return (stack, None);
8243        }
8244        let mut attrs = self.clone();
8245        let mut last_off = cur + attrs.pos;
8246        let mut missing = None;
8247        while let Some(attr) = attrs.next() {
8248            let Ok(attr) = attr else { break };
8249            match attr {
8250                OpGetDoReply::TupleOrig(val) => {
8251                    (stack, missing) = val.lookup_attr(offset, missing_type);
8252                    if !stack.is_empty() {
8253                        break;
8254                    }
8255                }
8256                OpGetDoReply::TupleReply(val) => {
8257                    (stack, missing) = val.lookup_attr(offset, missing_type);
8258                    if !stack.is_empty() {
8259                        break;
8260                    }
8261                }
8262                OpGetDoReply::Status(val) => {
8263                    if last_off == offset {
8264                        stack.push(("Status", last_off));
8265                        break;
8266                    }
8267                }
8268                OpGetDoReply::Protoinfo(val) => {
8269                    (stack, missing) = val.lookup_attr(offset, missing_type);
8270                    if !stack.is_empty() {
8271                        break;
8272                    }
8273                }
8274                OpGetDoReply::Help(val) => {
8275                    (stack, missing) = val.lookup_attr(offset, missing_type);
8276                    if !stack.is_empty() {
8277                        break;
8278                    }
8279                }
8280                OpGetDoReply::NatSrc(val) => {
8281                    (stack, missing) = val.lookup_attr(offset, missing_type);
8282                    if !stack.is_empty() {
8283                        break;
8284                    }
8285                }
8286                OpGetDoReply::Timeout(val) => {
8287                    if last_off == offset {
8288                        stack.push(("Timeout", last_off));
8289                        break;
8290                    }
8291                }
8292                OpGetDoReply::Mark(val) => {
8293                    if last_off == offset {
8294                        stack.push(("Mark", last_off));
8295                        break;
8296                    }
8297                }
8298                OpGetDoReply::CountersOrig(val) => {
8299                    (stack, missing) = val.lookup_attr(offset, missing_type);
8300                    if !stack.is_empty() {
8301                        break;
8302                    }
8303                }
8304                OpGetDoReply::CountersReply(val) => {
8305                    (stack, missing) = val.lookup_attr(offset, missing_type);
8306                    if !stack.is_empty() {
8307                        break;
8308                    }
8309                }
8310                OpGetDoReply::Use(val) => {
8311                    if last_off == offset {
8312                        stack.push(("Use", last_off));
8313                        break;
8314                    }
8315                }
8316                OpGetDoReply::Id(val) => {
8317                    if last_off == offset {
8318                        stack.push(("Id", last_off));
8319                        break;
8320                    }
8321                }
8322                OpGetDoReply::NatDst(val) => {
8323                    (stack, missing) = val.lookup_attr(offset, missing_type);
8324                    if !stack.is_empty() {
8325                        break;
8326                    }
8327                }
8328                OpGetDoReply::TupleMaster(val) => {
8329                    (stack, missing) = val.lookup_attr(offset, missing_type);
8330                    if !stack.is_empty() {
8331                        break;
8332                    }
8333                }
8334                OpGetDoReply::SeqAdjOrig(val) => {
8335                    (stack, missing) = val.lookup_attr(offset, missing_type);
8336                    if !stack.is_empty() {
8337                        break;
8338                    }
8339                }
8340                OpGetDoReply::SeqAdjReply(val) => {
8341                    (stack, missing) = val.lookup_attr(offset, missing_type);
8342                    if !stack.is_empty() {
8343                        break;
8344                    }
8345                }
8346                OpGetDoReply::Zone(val) => {
8347                    if last_off == offset {
8348                        stack.push(("Zone", last_off));
8349                        break;
8350                    }
8351                }
8352                OpGetDoReply::Secctx(val) => {
8353                    (stack, missing) = val.lookup_attr(offset, missing_type);
8354                    if !stack.is_empty() {
8355                        break;
8356                    }
8357                }
8358                OpGetDoReply::Labels(val) => {
8359                    if last_off == offset {
8360                        stack.push(("Labels", last_off));
8361                        break;
8362                    }
8363                }
8364                OpGetDoReply::Synproxy(val) => {
8365                    (stack, missing) = val.lookup_attr(offset, missing_type);
8366                    if !stack.is_empty() {
8367                        break;
8368                    }
8369                }
8370                _ => {}
8371            };
8372            last_off = cur + attrs.pos;
8373        }
8374        if !stack.is_empty() {
8375            stack.push(("OpGetDoReply", cur));
8376        }
8377        (stack, missing)
8378    }
8379}
8380#[derive(Debug)]
8381pub struct RequestOpGetDoRequest<'r> {
8382    request: Request<'r>,
8383}
8384impl<'r> RequestOpGetDoRequest<'r> {
8385    pub fn new(mut request: Request<'r>, header: &PushNfgenmsg) -> Self {
8386        PushOpGetDoRequest::write_header(&mut request.buf_mut(), header);
8387        Self { request: request }
8388    }
8389    pub fn encode(&mut self) -> PushOpGetDoRequest<&mut Vec<u8>> {
8390        PushOpGetDoRequest::new_without_header(self.request.buf_mut())
8391    }
8392    pub fn into_encoder(self) -> PushOpGetDoRequest<RequestBuf<'r>> {
8393        PushOpGetDoRequest::new_without_header(self.request.buf)
8394    }
8395    pub fn decode_request<'buf>(buf: &'buf [u8]) -> (PushNfgenmsg, IterableOpGetDoRequest<'buf>) {
8396        OpGetDoRequest::new(buf)
8397    }
8398}
8399impl NetlinkRequest for RequestOpGetDoRequest<'_> {
8400    fn protocol(&self) -> Protocol {
8401        Protocol::Raw {
8402            protonum: 12u16,
8403            request_type: 257u16,
8404        }
8405    }
8406    fn flags(&self) -> u16 {
8407        self.request.flags
8408    }
8409    fn payload(&self) -> &[u8] {
8410        self.request.buf()
8411    }
8412    type ReplyType<'buf> = (PushNfgenmsg, IterableOpGetDoReply<'buf>);
8413    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
8414        OpGetDoReply::new(buf)
8415    }
8416    fn lookup(
8417        buf: &[u8],
8418        offset: usize,
8419        missing_type: Option<u16>,
8420    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8421        OpGetDoRequest::new(buf).1.lookup_attr(offset, missing_type)
8422    }
8423}
8424#[doc = "dump pcpu conntrack stats"]
8425pub struct PushOpGetStatsDumpRequest<Prev: Rec> {
8426    pub(crate) prev: Option<Prev>,
8427    pub(crate) header_offset: Option<usize>,
8428}
8429impl<Prev: Rec> Rec for PushOpGetStatsDumpRequest<Prev> {
8430    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8431        self.prev.as_mut().unwrap().as_rec_mut()
8432    }
8433    fn as_rec(&self) -> &Vec<u8> {
8434        self.prev.as_ref().unwrap().as_rec()
8435    }
8436}
8437impl<Prev: Rec> PushOpGetStatsDumpRequest<Prev> {
8438    pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
8439        Self::write_header(&mut prev, header);
8440        Self::new_without_header(prev)
8441    }
8442    fn new_without_header(prev: Prev) -> Self {
8443        Self {
8444            prev: Some(prev),
8445            header_offset: None,
8446        }
8447    }
8448    fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
8449        prev.as_rec_mut().extend(header.as_slice());
8450    }
8451    pub fn end_nested(mut self) -> Prev {
8452        let mut prev = self.prev.take().unwrap();
8453        if let Some(header_offset) = &self.header_offset {
8454            finalize_nested_header(prev.as_rec_mut(), *header_offset);
8455        }
8456        prev
8457    }
8458}
8459impl<Prev: Rec> Drop for PushOpGetStatsDumpRequest<Prev> {
8460    fn drop(&mut self) {
8461        if let Some(prev) = &mut self.prev {
8462            if let Some(header_offset) = &self.header_offset {
8463                finalize_nested_header(prev.as_rec_mut(), *header_offset);
8464            }
8465        }
8466    }
8467}
8468#[doc = "dump pcpu conntrack stats"]
8469#[derive(Clone)]
8470pub enum OpGetStatsDumpRequest {}
8471impl<'a> IterableOpGetStatsDumpRequest<'a> {}
8472impl OpGetStatsDumpRequest {
8473    pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetStatsDumpRequest<'a>) {
8474        let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
8475        (
8476            PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
8477            IterableOpGetStatsDumpRequest::with_loc(attrs, buf.as_ptr() as usize),
8478        )
8479    }
8480    fn attr_from_type(r#type: u16) -> Option<&'static str> {
8481        ConntrackStatsAttrs::attr_from_type(r#type)
8482    }
8483}
8484#[derive(Clone, Copy, Default)]
8485pub struct IterableOpGetStatsDumpRequest<'a> {
8486    buf: &'a [u8],
8487    pos: usize,
8488    orig_loc: usize,
8489}
8490impl<'a> IterableOpGetStatsDumpRequest<'a> {
8491    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8492        Self {
8493            buf,
8494            pos: 0,
8495            orig_loc,
8496        }
8497    }
8498    pub fn get_buf(&self) -> &'a [u8] {
8499        self.buf
8500    }
8501}
8502impl<'a> Iterator for IterableOpGetStatsDumpRequest<'a> {
8503    type Item = Result<OpGetStatsDumpRequest, ErrorContext>;
8504    fn next(&mut self) -> Option<Self::Item> {
8505        let pos = self.pos;
8506        let mut r#type;
8507        loop {
8508            r#type = None;
8509            if self.buf.len() == self.pos {
8510                return None;
8511            }
8512            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8513                break;
8514            };
8515            r#type = Some(header.r#type);
8516            let res = match header.r#type {
8517                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8518                n => continue,
8519            };
8520            return Some(Ok(res));
8521        }
8522        Some(Err(ErrorContext::new(
8523            "OpGetStatsDumpRequest",
8524            r#type.and_then(|t| OpGetStatsDumpRequest::attr_from_type(t)),
8525            self.orig_loc,
8526            self.buf.as_ptr().wrapping_add(pos) as usize,
8527        )))
8528    }
8529}
8530impl std::fmt::Debug for IterableOpGetStatsDumpRequest<'_> {
8531    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8532        let mut fmt = f.debug_struct("OpGetStatsDumpRequest");
8533        for attr in self.clone() {
8534            let attr = match attr {
8535                Ok(a) => a,
8536                Err(err) => {
8537                    fmt.finish()?;
8538                    f.write_str("Err(")?;
8539                    err.fmt(f)?;
8540                    return f.write_str(")");
8541                }
8542            };
8543            match attr {};
8544        }
8545        fmt.finish()
8546    }
8547}
8548impl IterableOpGetStatsDumpRequest<'_> {
8549    pub fn lookup_attr(
8550        &self,
8551        offset: usize,
8552        missing_type: Option<u16>,
8553    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8554        let mut stack = Vec::new();
8555        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8556        if cur == offset + PushNfgenmsg::len() {
8557            stack.push(("OpGetStatsDumpRequest", offset));
8558            return (
8559                stack,
8560                missing_type.and_then(|t| OpGetStatsDumpRequest::attr_from_type(t)),
8561            );
8562        }
8563        (stack, None)
8564    }
8565}
8566#[doc = "dump pcpu conntrack stats"]
8567pub struct PushOpGetStatsDumpReply<Prev: Rec> {
8568    pub(crate) prev: Option<Prev>,
8569    pub(crate) header_offset: Option<usize>,
8570}
8571impl<Prev: Rec> Rec for PushOpGetStatsDumpReply<Prev> {
8572    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8573        self.prev.as_mut().unwrap().as_rec_mut()
8574    }
8575    fn as_rec(&self) -> &Vec<u8> {
8576        self.prev.as_ref().unwrap().as_rec()
8577    }
8578}
8579impl<Prev: Rec> PushOpGetStatsDumpReply<Prev> {
8580    pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
8581        Self::write_header(&mut prev, header);
8582        Self::new_without_header(prev)
8583    }
8584    fn new_without_header(prev: Prev) -> Self {
8585        Self {
8586            prev: Some(prev),
8587            header_offset: None,
8588        }
8589    }
8590    fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
8591        prev.as_rec_mut().extend(header.as_slice());
8592    }
8593    pub fn end_nested(mut self) -> Prev {
8594        let mut prev = self.prev.take().unwrap();
8595        if let Some(header_offset) = &self.header_offset {
8596            finalize_nested_header(prev.as_rec_mut(), *header_offset);
8597        }
8598        prev
8599    }
8600    #[doc = "obsolete"]
8601    pub fn push_searched(mut self, value: u32) -> Self {
8602        push_header(self.as_rec_mut(), 1u16, 4 as u16);
8603        self.as_rec_mut().extend(value.to_be_bytes());
8604        self
8605    }
8606    pub fn push_found(mut self, value: u32) -> Self {
8607        push_header(self.as_rec_mut(), 2u16, 4 as u16);
8608        self.as_rec_mut().extend(value.to_be_bytes());
8609        self
8610    }
8611    pub fn push_insert(mut self, value: u32) -> Self {
8612        push_header(self.as_rec_mut(), 8u16, 4 as u16);
8613        self.as_rec_mut().extend(value.to_be_bytes());
8614        self
8615    }
8616    pub fn push_insert_failed(mut self, value: u32) -> Self {
8617        push_header(self.as_rec_mut(), 9u16, 4 as u16);
8618        self.as_rec_mut().extend(value.to_be_bytes());
8619        self
8620    }
8621    pub fn push_drop(mut self, value: u32) -> Self {
8622        push_header(self.as_rec_mut(), 10u16, 4 as u16);
8623        self.as_rec_mut().extend(value.to_be_bytes());
8624        self
8625    }
8626    pub fn push_early_drop(mut self, value: u32) -> Self {
8627        push_header(self.as_rec_mut(), 11u16, 4 as u16);
8628        self.as_rec_mut().extend(value.to_be_bytes());
8629        self
8630    }
8631    pub fn push_error(mut self, value: u32) -> Self {
8632        push_header(self.as_rec_mut(), 12u16, 4 as u16);
8633        self.as_rec_mut().extend(value.to_be_bytes());
8634        self
8635    }
8636    pub fn push_search_restart(mut self, value: u32) -> Self {
8637        push_header(self.as_rec_mut(), 13u16, 4 as u16);
8638        self.as_rec_mut().extend(value.to_be_bytes());
8639        self
8640    }
8641    pub fn push_clash_resolve(mut self, value: u32) -> Self {
8642        push_header(self.as_rec_mut(), 14u16, 4 as u16);
8643        self.as_rec_mut().extend(value.to_be_bytes());
8644        self
8645    }
8646    pub fn push_chain_toolong(mut self, value: u32) -> Self {
8647        push_header(self.as_rec_mut(), 15u16, 4 as u16);
8648        self.as_rec_mut().extend(value.to_be_bytes());
8649        self
8650    }
8651}
8652impl<Prev: Rec> Drop for PushOpGetStatsDumpReply<Prev> {
8653    fn drop(&mut self) {
8654        if let Some(prev) = &mut self.prev {
8655            if let Some(header_offset) = &self.header_offset {
8656                finalize_nested_header(prev.as_rec_mut(), *header_offset);
8657            }
8658        }
8659    }
8660}
8661#[doc = "dump pcpu conntrack stats"]
8662#[derive(Clone)]
8663pub enum OpGetStatsDumpReply {
8664    #[doc = "obsolete"]
8665    Searched(u32),
8666    Found(u32),
8667    Insert(u32),
8668    InsertFailed(u32),
8669    Drop(u32),
8670    EarlyDrop(u32),
8671    Error(u32),
8672    SearchRestart(u32),
8673    ClashResolve(u32),
8674    ChainToolong(u32),
8675}
8676impl<'a> IterableOpGetStatsDumpReply<'a> {
8677    #[doc = "obsolete"]
8678    pub fn get_searched(&self) -> Result<u32, ErrorContext> {
8679        let mut iter = self.clone();
8680        iter.pos = 0;
8681        for attr in iter {
8682            if let OpGetStatsDumpReply::Searched(val) = attr? {
8683                return Ok(val);
8684            }
8685        }
8686        Err(ErrorContext::new_missing(
8687            "OpGetStatsDumpReply",
8688            "Searched",
8689            self.orig_loc,
8690            self.buf.as_ptr() as usize,
8691        ))
8692    }
8693    pub fn get_found(&self) -> Result<u32, ErrorContext> {
8694        let mut iter = self.clone();
8695        iter.pos = 0;
8696        for attr in iter {
8697            if let OpGetStatsDumpReply::Found(val) = attr? {
8698                return Ok(val);
8699            }
8700        }
8701        Err(ErrorContext::new_missing(
8702            "OpGetStatsDumpReply",
8703            "Found",
8704            self.orig_loc,
8705            self.buf.as_ptr() as usize,
8706        ))
8707    }
8708    pub fn get_insert(&self) -> Result<u32, ErrorContext> {
8709        let mut iter = self.clone();
8710        iter.pos = 0;
8711        for attr in iter {
8712            if let OpGetStatsDumpReply::Insert(val) = attr? {
8713                return Ok(val);
8714            }
8715        }
8716        Err(ErrorContext::new_missing(
8717            "OpGetStatsDumpReply",
8718            "Insert",
8719            self.orig_loc,
8720            self.buf.as_ptr() as usize,
8721        ))
8722    }
8723    pub fn get_insert_failed(&self) -> Result<u32, ErrorContext> {
8724        let mut iter = self.clone();
8725        iter.pos = 0;
8726        for attr in iter {
8727            if let OpGetStatsDumpReply::InsertFailed(val) = attr? {
8728                return Ok(val);
8729            }
8730        }
8731        Err(ErrorContext::new_missing(
8732            "OpGetStatsDumpReply",
8733            "InsertFailed",
8734            self.orig_loc,
8735            self.buf.as_ptr() as usize,
8736        ))
8737    }
8738    pub fn get_drop(&self) -> Result<u32, ErrorContext> {
8739        let mut iter = self.clone();
8740        iter.pos = 0;
8741        for attr in iter {
8742            if let OpGetStatsDumpReply::Drop(val) = attr? {
8743                return Ok(val);
8744            }
8745        }
8746        Err(ErrorContext::new_missing(
8747            "OpGetStatsDumpReply",
8748            "Drop",
8749            self.orig_loc,
8750            self.buf.as_ptr() as usize,
8751        ))
8752    }
8753    pub fn get_early_drop(&self) -> Result<u32, ErrorContext> {
8754        let mut iter = self.clone();
8755        iter.pos = 0;
8756        for attr in iter {
8757            if let OpGetStatsDumpReply::EarlyDrop(val) = attr? {
8758                return Ok(val);
8759            }
8760        }
8761        Err(ErrorContext::new_missing(
8762            "OpGetStatsDumpReply",
8763            "EarlyDrop",
8764            self.orig_loc,
8765            self.buf.as_ptr() as usize,
8766        ))
8767    }
8768    pub fn get_error(&self) -> Result<u32, ErrorContext> {
8769        let mut iter = self.clone();
8770        iter.pos = 0;
8771        for attr in iter {
8772            if let OpGetStatsDumpReply::Error(val) = attr? {
8773                return Ok(val);
8774            }
8775        }
8776        Err(ErrorContext::new_missing(
8777            "OpGetStatsDumpReply",
8778            "Error",
8779            self.orig_loc,
8780            self.buf.as_ptr() as usize,
8781        ))
8782    }
8783    pub fn get_search_restart(&self) -> Result<u32, ErrorContext> {
8784        let mut iter = self.clone();
8785        iter.pos = 0;
8786        for attr in iter {
8787            if let OpGetStatsDumpReply::SearchRestart(val) = attr? {
8788                return Ok(val);
8789            }
8790        }
8791        Err(ErrorContext::new_missing(
8792            "OpGetStatsDumpReply",
8793            "SearchRestart",
8794            self.orig_loc,
8795            self.buf.as_ptr() as usize,
8796        ))
8797    }
8798    pub fn get_clash_resolve(&self) -> Result<u32, ErrorContext> {
8799        let mut iter = self.clone();
8800        iter.pos = 0;
8801        for attr in iter {
8802            if let OpGetStatsDumpReply::ClashResolve(val) = attr? {
8803                return Ok(val);
8804            }
8805        }
8806        Err(ErrorContext::new_missing(
8807            "OpGetStatsDumpReply",
8808            "ClashResolve",
8809            self.orig_loc,
8810            self.buf.as_ptr() as usize,
8811        ))
8812    }
8813    pub fn get_chain_toolong(&self) -> Result<u32, ErrorContext> {
8814        let mut iter = self.clone();
8815        iter.pos = 0;
8816        for attr in iter {
8817            if let OpGetStatsDumpReply::ChainToolong(val) = attr? {
8818                return Ok(val);
8819            }
8820        }
8821        Err(ErrorContext::new_missing(
8822            "OpGetStatsDumpReply",
8823            "ChainToolong",
8824            self.orig_loc,
8825            self.buf.as_ptr() as usize,
8826        ))
8827    }
8828}
8829impl OpGetStatsDumpReply {
8830    pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetStatsDumpReply<'a>) {
8831        let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
8832        (
8833            PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
8834            IterableOpGetStatsDumpReply::with_loc(attrs, buf.as_ptr() as usize),
8835        )
8836    }
8837    fn attr_from_type(r#type: u16) -> Option<&'static str> {
8838        ConntrackStatsAttrs::attr_from_type(r#type)
8839    }
8840}
8841#[derive(Clone, Copy, Default)]
8842pub struct IterableOpGetStatsDumpReply<'a> {
8843    buf: &'a [u8],
8844    pos: usize,
8845    orig_loc: usize,
8846}
8847impl<'a> IterableOpGetStatsDumpReply<'a> {
8848    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8849        Self {
8850            buf,
8851            pos: 0,
8852            orig_loc,
8853        }
8854    }
8855    pub fn get_buf(&self) -> &'a [u8] {
8856        self.buf
8857    }
8858}
8859impl<'a> Iterator for IterableOpGetStatsDumpReply<'a> {
8860    type Item = Result<OpGetStatsDumpReply, ErrorContext>;
8861    fn next(&mut self) -> Option<Self::Item> {
8862        let pos = self.pos;
8863        let mut r#type;
8864        loop {
8865            r#type = None;
8866            if self.buf.len() == self.pos {
8867                return None;
8868            }
8869            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8870                break;
8871            };
8872            r#type = Some(header.r#type);
8873            let res = match header.r#type {
8874                1u16 => OpGetStatsDumpReply::Searched({
8875                    let res = parse_be_u32(next);
8876                    let Some(val) = res else { break };
8877                    val
8878                }),
8879                2u16 => OpGetStatsDumpReply::Found({
8880                    let res = parse_be_u32(next);
8881                    let Some(val) = res else { break };
8882                    val
8883                }),
8884                8u16 => OpGetStatsDumpReply::Insert({
8885                    let res = parse_be_u32(next);
8886                    let Some(val) = res else { break };
8887                    val
8888                }),
8889                9u16 => OpGetStatsDumpReply::InsertFailed({
8890                    let res = parse_be_u32(next);
8891                    let Some(val) = res else { break };
8892                    val
8893                }),
8894                10u16 => OpGetStatsDumpReply::Drop({
8895                    let res = parse_be_u32(next);
8896                    let Some(val) = res else { break };
8897                    val
8898                }),
8899                11u16 => OpGetStatsDumpReply::EarlyDrop({
8900                    let res = parse_be_u32(next);
8901                    let Some(val) = res else { break };
8902                    val
8903                }),
8904                12u16 => OpGetStatsDumpReply::Error({
8905                    let res = parse_be_u32(next);
8906                    let Some(val) = res else { break };
8907                    val
8908                }),
8909                13u16 => OpGetStatsDumpReply::SearchRestart({
8910                    let res = parse_be_u32(next);
8911                    let Some(val) = res else { break };
8912                    val
8913                }),
8914                14u16 => OpGetStatsDumpReply::ClashResolve({
8915                    let res = parse_be_u32(next);
8916                    let Some(val) = res else { break };
8917                    val
8918                }),
8919                15u16 => OpGetStatsDumpReply::ChainToolong({
8920                    let res = parse_be_u32(next);
8921                    let Some(val) = res else { break };
8922                    val
8923                }),
8924                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8925                n => continue,
8926            };
8927            return Some(Ok(res));
8928        }
8929        Some(Err(ErrorContext::new(
8930            "OpGetStatsDumpReply",
8931            r#type.and_then(|t| OpGetStatsDumpReply::attr_from_type(t)),
8932            self.orig_loc,
8933            self.buf.as_ptr().wrapping_add(pos) as usize,
8934        )))
8935    }
8936}
8937impl std::fmt::Debug for IterableOpGetStatsDumpReply<'_> {
8938    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8939        let mut fmt = f.debug_struct("OpGetStatsDumpReply");
8940        for attr in self.clone() {
8941            let attr = match attr {
8942                Ok(a) => a,
8943                Err(err) => {
8944                    fmt.finish()?;
8945                    f.write_str("Err(")?;
8946                    err.fmt(f)?;
8947                    return f.write_str(")");
8948                }
8949            };
8950            match attr {
8951                OpGetStatsDumpReply::Searched(val) => fmt.field("Searched", &val),
8952                OpGetStatsDumpReply::Found(val) => fmt.field("Found", &val),
8953                OpGetStatsDumpReply::Insert(val) => fmt.field("Insert", &val),
8954                OpGetStatsDumpReply::InsertFailed(val) => fmt.field("InsertFailed", &val),
8955                OpGetStatsDumpReply::Drop(val) => fmt.field("Drop", &val),
8956                OpGetStatsDumpReply::EarlyDrop(val) => fmt.field("EarlyDrop", &val),
8957                OpGetStatsDumpReply::Error(val) => fmt.field("Error", &val),
8958                OpGetStatsDumpReply::SearchRestart(val) => fmt.field("SearchRestart", &val),
8959                OpGetStatsDumpReply::ClashResolve(val) => fmt.field("ClashResolve", &val),
8960                OpGetStatsDumpReply::ChainToolong(val) => fmt.field("ChainToolong", &val),
8961            };
8962        }
8963        fmt.finish()
8964    }
8965}
8966impl IterableOpGetStatsDumpReply<'_> {
8967    pub fn lookup_attr(
8968        &self,
8969        offset: usize,
8970        missing_type: Option<u16>,
8971    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8972        let mut stack = Vec::new();
8973        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8974        if cur == offset + PushNfgenmsg::len() {
8975            stack.push(("OpGetStatsDumpReply", offset));
8976            return (
8977                stack,
8978                missing_type.and_then(|t| OpGetStatsDumpReply::attr_from_type(t)),
8979            );
8980        }
8981        if cur > offset || cur + self.buf.len() < offset {
8982            return (stack, None);
8983        }
8984        let mut attrs = self.clone();
8985        let mut last_off = cur + attrs.pos;
8986        while let Some(attr) = attrs.next() {
8987            let Ok(attr) = attr else { break };
8988            match attr {
8989                OpGetStatsDumpReply::Searched(val) => {
8990                    if last_off == offset {
8991                        stack.push(("Searched", last_off));
8992                        break;
8993                    }
8994                }
8995                OpGetStatsDumpReply::Found(val) => {
8996                    if last_off == offset {
8997                        stack.push(("Found", last_off));
8998                        break;
8999                    }
9000                }
9001                OpGetStatsDumpReply::Insert(val) => {
9002                    if last_off == offset {
9003                        stack.push(("Insert", last_off));
9004                        break;
9005                    }
9006                }
9007                OpGetStatsDumpReply::InsertFailed(val) => {
9008                    if last_off == offset {
9009                        stack.push(("InsertFailed", last_off));
9010                        break;
9011                    }
9012                }
9013                OpGetStatsDumpReply::Drop(val) => {
9014                    if last_off == offset {
9015                        stack.push(("Drop", last_off));
9016                        break;
9017                    }
9018                }
9019                OpGetStatsDumpReply::EarlyDrop(val) => {
9020                    if last_off == offset {
9021                        stack.push(("EarlyDrop", last_off));
9022                        break;
9023                    }
9024                }
9025                OpGetStatsDumpReply::Error(val) => {
9026                    if last_off == offset {
9027                        stack.push(("Error", last_off));
9028                        break;
9029                    }
9030                }
9031                OpGetStatsDumpReply::SearchRestart(val) => {
9032                    if last_off == offset {
9033                        stack.push(("SearchRestart", last_off));
9034                        break;
9035                    }
9036                }
9037                OpGetStatsDumpReply::ClashResolve(val) => {
9038                    if last_off == offset {
9039                        stack.push(("ClashResolve", last_off));
9040                        break;
9041                    }
9042                }
9043                OpGetStatsDumpReply::ChainToolong(val) => {
9044                    if last_off == offset {
9045                        stack.push(("ChainToolong", last_off));
9046                        break;
9047                    }
9048                }
9049                _ => {}
9050            };
9051            last_off = cur + attrs.pos;
9052        }
9053        if !stack.is_empty() {
9054            stack.push(("OpGetStatsDumpReply", cur));
9055        }
9056        (stack, None)
9057    }
9058}
9059#[derive(Debug)]
9060pub struct RequestOpGetStatsDumpRequest<'r> {
9061    request: Request<'r>,
9062}
9063impl<'r> RequestOpGetStatsDumpRequest<'r> {
9064    pub fn new(mut request: Request<'r>, header: &PushNfgenmsg) -> Self {
9065        PushOpGetStatsDumpRequest::write_header(&mut request.buf_mut(), header);
9066        Self {
9067            request: request.set_dump(),
9068        }
9069    }
9070    pub fn encode(&mut self) -> PushOpGetStatsDumpRequest<&mut Vec<u8>> {
9071        PushOpGetStatsDumpRequest::new_without_header(self.request.buf_mut())
9072    }
9073    pub fn into_encoder(self) -> PushOpGetStatsDumpRequest<RequestBuf<'r>> {
9074        PushOpGetStatsDumpRequest::new_without_header(self.request.buf)
9075    }
9076    pub fn decode_request<'buf>(
9077        buf: &'buf [u8],
9078    ) -> (PushNfgenmsg, IterableOpGetStatsDumpRequest<'buf>) {
9079        OpGetStatsDumpRequest::new(buf)
9080    }
9081}
9082impl NetlinkRequest for RequestOpGetStatsDumpRequest<'_> {
9083    fn protocol(&self) -> Protocol {
9084        Protocol::Raw {
9085            protonum: 12u16,
9086            request_type: 260u16,
9087        }
9088    }
9089    fn flags(&self) -> u16 {
9090        self.request.flags
9091    }
9092    fn payload(&self) -> &[u8] {
9093        self.request.buf()
9094    }
9095    type ReplyType<'buf> = (PushNfgenmsg, IterableOpGetStatsDumpReply<'buf>);
9096    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
9097        OpGetStatsDumpReply::new(buf)
9098    }
9099    fn lookup(
9100        buf: &[u8],
9101        offset: usize,
9102        missing_type: Option<u16>,
9103    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9104        OpGetStatsDumpRequest::new(buf)
9105            .1
9106            .lookup_attr(offset, missing_type)
9107    }
9108}
9109#[derive(Debug)]
9110pub struct ChainedFinal<'a> {
9111    inner: Chained<'a>,
9112}
9113#[derive(Debug)]
9114pub struct Chained<'a> {
9115    buf: RequestBuf<'a>,
9116    first_seq: u32,
9117    lookups: Vec<(&'static str, LookupFn)>,
9118    last_header_offset: usize,
9119    last_kind: Option<RequestInfo>,
9120}
9121impl<'a> ChainedFinal<'a> {
9122    pub fn into_chained(self) -> Chained<'a> {
9123        self.inner
9124    }
9125    pub fn buf(&self) -> &Vec<u8> {
9126        self.inner.buf()
9127    }
9128    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
9129        self.inner.buf_mut()
9130    }
9131    fn get_index(&self, seq: u32) -> Option<u32> {
9132        let min = self.inner.first_seq;
9133        let max = min.wrapping_add(self.inner.lookups.len() as u32);
9134        return if min <= max {
9135            (min..max).contains(&seq).then(|| seq - min)
9136        } else if min <= seq {
9137            Some(seq - min)
9138        } else if seq < max {
9139            Some(u32::MAX - min + seq)
9140        } else {
9141            None
9142        };
9143    }
9144}
9145impl crate::traits::NetlinkChained for ChainedFinal<'_> {
9146    fn protonum(&self) -> u16 {
9147        PROTONUM
9148    }
9149    fn payload(&self) -> &[u8] {
9150        self.buf()
9151    }
9152    fn chain_len(&self) -> usize {
9153        self.inner.lookups.len()
9154    }
9155    fn get_index(&self, seq: u32) -> Option<usize> {
9156        self.get_index(seq).map(|n| n as usize)
9157    }
9158    fn name(&self, index: usize) -> &'static str {
9159        self.inner.lookups[index].0
9160    }
9161    fn lookup(&self, index: usize) -> LookupFn {
9162        self.inner.lookups[index].1
9163    }
9164}
9165impl Chained<'static> {
9166    pub fn new(first_seq: u32) -> Self {
9167        Self::new_from_buf(Vec::new(), first_seq)
9168    }
9169    pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
9170        Self {
9171            buf: RequestBuf::Own(buf),
9172            first_seq,
9173            lookups: Vec::new(),
9174            last_header_offset: 0,
9175            last_kind: None,
9176        }
9177    }
9178    pub fn into_buf(self) -> Vec<u8> {
9179        match self.buf {
9180            RequestBuf::Own(buf) => buf,
9181            _ => unreachable!(),
9182        }
9183    }
9184}
9185impl<'a> Chained<'a> {
9186    pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
9187        Self {
9188            buf: RequestBuf::Ref(buf),
9189            first_seq,
9190            lookups: Vec::new(),
9191            last_header_offset: 0,
9192            last_kind: None,
9193        }
9194    }
9195    pub fn finalize(mut self) -> ChainedFinal<'a> {
9196        self.update_header();
9197        ChainedFinal { inner: self }
9198    }
9199    pub fn request(&mut self) -> Request<'_> {
9200        self.update_header();
9201        self.last_header_offset = self.buf().len();
9202        self.buf_mut()
9203            .extend_from_slice(PushNlmsghdr::new().as_slice());
9204        let mut request = Request::new_extend(self.buf.buf_mut());
9205        self.last_kind = None;
9206        request.writeback = Some(&mut self.last_kind);
9207        request
9208    }
9209    pub fn buf(&self) -> &Vec<u8> {
9210        self.buf.buf()
9211    }
9212    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
9213        self.buf.buf_mut()
9214    }
9215    fn update_header(&mut self) {
9216        let Some(RequestInfo {
9217            protocol,
9218            flags,
9219            name,
9220            lookup,
9221        }) = self.last_kind
9222        else {
9223            if !self.buf().is_empty() {
9224                assert_eq!(
9225                    self.last_header_offset + PushNlmsghdr::len(),
9226                    self.buf().len()
9227                );
9228                self.buf.buf_mut().truncate(self.last_header_offset);
9229            }
9230            return;
9231        };
9232        let header_offset = self.last_header_offset;
9233        let request_type = match protocol {
9234            Protocol::Raw { request_type, .. } => request_type,
9235            Protocol::Generic(_) => unreachable!(),
9236        };
9237        let index = self.lookups.len();
9238        let seq = self.first_seq.wrapping_add(index as u32);
9239        self.lookups.push((name, lookup));
9240        let buf = self.buf_mut();
9241        align(buf);
9242        let mut header = PushNlmsghdr::new();
9243        header.set_len((buf.len() - header_offset) as u32);
9244        header.set_type(request_type);
9245        header.set_flags(flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16);
9246        header.set_seq(seq);
9247        buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
9248    }
9249}
9250use crate::traits::LookupFn;
9251use crate::utils::RequestBuf;
9252#[derive(Debug)]
9253pub struct Request<'buf> {
9254    buf: RequestBuf<'buf>,
9255    flags: u16,
9256    writeback: Option<&'buf mut Option<RequestInfo>>,
9257}
9258#[allow(unused)]
9259#[derive(Debug, Clone)]
9260pub struct RequestInfo {
9261    protocol: Protocol,
9262    flags: u16,
9263    name: &'static str,
9264    lookup: LookupFn,
9265}
9266impl Request<'static> {
9267    pub fn new() -> Self {
9268        Self::new_from_buf(Vec::new())
9269    }
9270    pub fn new_from_buf(buf: Vec<u8>) -> Self {
9271        Self {
9272            flags: 0,
9273            buf: RequestBuf::Own(buf),
9274            writeback: None,
9275        }
9276    }
9277    pub fn into_buf(self) -> Vec<u8> {
9278        match self.buf {
9279            RequestBuf::Own(buf) => buf,
9280            _ => unreachable!(),
9281        }
9282    }
9283}
9284impl<'buf> Request<'buf> {
9285    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
9286        buf.clear();
9287        Self::new_extend(buf)
9288    }
9289    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
9290        Self {
9291            flags: 0,
9292            buf: RequestBuf::Ref(buf),
9293            writeback: None,
9294        }
9295    }
9296    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
9297        let Some(writeback) = &mut self.writeback else {
9298            return;
9299        };
9300        **writeback = Some(RequestInfo {
9301            protocol,
9302            flags: self.flags,
9303            name,
9304            lookup,
9305        })
9306    }
9307    pub fn buf(&self) -> &Vec<u8> {
9308        self.buf.buf()
9309    }
9310    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
9311        self.buf.buf_mut()
9312    }
9313    #[doc = "Set `NLM_F_CREATE` flag"]
9314    pub fn set_create(mut self) -> Self {
9315        self.flags |= consts::NLM_F_CREATE as u16;
9316        self
9317    }
9318    #[doc = "Set `NLM_F_EXCL` flag"]
9319    pub fn set_excl(mut self) -> Self {
9320        self.flags |= consts::NLM_F_EXCL as u16;
9321        self
9322    }
9323    #[doc = "Set `NLM_F_REPLACE` flag"]
9324    pub fn set_replace(mut self) -> Self {
9325        self.flags |= consts::NLM_F_REPLACE as u16;
9326        self
9327    }
9328    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
9329    pub fn set_change(self) -> Self {
9330        self.set_create().set_replace()
9331    }
9332    #[doc = "Set `NLM_F_APPEND` flag"]
9333    pub fn set_append(mut self) -> Self {
9334        self.flags |= consts::NLM_F_APPEND as u16;
9335        self
9336    }
9337    #[doc = "Set `NLM_F_DUMP` flag"]
9338    fn set_dump(mut self) -> Self {
9339        self.flags |= consts::NLM_F_DUMP as u16;
9340        self
9341    }
9342    pub fn op_get_dump_request(self, header: &PushNfgenmsg) -> RequestOpGetDumpRequest<'buf> {
9343        let mut res = RequestOpGetDumpRequest::new(self, header);
9344        res.request.do_writeback(
9345            res.protocol(),
9346            "op-get-dump-request",
9347            RequestOpGetDumpRequest::lookup,
9348        );
9349        res
9350    }
9351    pub fn op_get_do_request(self, header: &PushNfgenmsg) -> RequestOpGetDoRequest<'buf> {
9352        let mut res = RequestOpGetDoRequest::new(self, header);
9353        res.request.do_writeback(
9354            res.protocol(),
9355            "op-get-do-request",
9356            RequestOpGetDoRequest::lookup,
9357        );
9358        res
9359    }
9360    pub fn op_get_stats_dump_request(
9361        self,
9362        header: &PushNfgenmsg,
9363    ) -> RequestOpGetStatsDumpRequest<'buf> {
9364        let mut res = RequestOpGetStatsDumpRequest::new(self, header);
9365        res.request.do_writeback(
9366            res.protocol(),
9367            "op-get-stats-dump-request",
9368            RequestOpGetStatsDumpRequest::lookup,
9369        );
9370        res
9371    }
9372}