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