Skip to main content

netlink_bindings/rt-rule/
mod.rs

1#![doc = "FIB rule management over rtnetlink\\."]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "rt-rule";
17pub const PROTONAME_CSTR: &CStr = c"rt-rule";
18pub const PROTONUM: u16 = 0u16;
19#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
20#[derive(Debug, Clone, Copy)]
21pub enum FrAct {
22    Unspec = 0,
23    ToTbl = 1,
24    Goto = 2,
25    Nop = 3,
26    Res3 = 4,
27    Res4 = 5,
28    Blackhole = 6,
29    Unreachable = 7,
30    Prohibit = 8,
31}
32impl FrAct {
33    pub fn from_value(value: u64) -> Option<Self> {
34        Some(match value {
35            0 => Self::Unspec,
36            1 => Self::ToTbl,
37            2 => Self::Goto,
38            3 => Self::Nop,
39            4 => Self::Res3,
40            5 => Self::Res4,
41            6 => Self::Blackhole,
42            7 => Self::Unreachable,
43            8 => Self::Prohibit,
44            _ => return None,
45        })
46    }
47}
48#[repr(C, packed(4))]
49pub struct Rtgenmsg {
50    pub family: u8,
51    pub _pad: [u8; 3usize],
52}
53impl Clone for Rtgenmsg {
54    fn clone(&self) -> Self {
55        Self::new_from_array(*self.as_array())
56    }
57}
58#[doc = "Create zero-initialized struct"]
59impl Default for Rtgenmsg {
60    fn default() -> Self {
61        Self::new()
62    }
63}
64impl Rtgenmsg {
65    #[doc = "Create zero-initialized struct"]
66    pub fn new() -> Self {
67        Self::new_from_array([0u8; Self::len()])
68    }
69    #[doc = "Copy from contents from slice"]
70    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
71        if other.len() != Self::len() {
72            return None;
73        }
74        let mut buf = [0u8; Self::len()];
75        buf.clone_from_slice(other);
76        Some(Self::new_from_array(buf))
77    }
78    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
79    pub fn new_from_zeroed(other: &[u8]) -> Self {
80        let mut buf = [0u8; Self::len()];
81        let len = buf.len().min(other.len());
82        buf[..len].clone_from_slice(&other[..len]);
83        Self::new_from_array(buf)
84    }
85    pub fn new_from_array(buf: [u8; 4usize]) -> Self {
86        unsafe { std::mem::transmute(buf) }
87    }
88    pub fn as_slice(&self) -> &[u8] {
89        unsafe {
90            let ptr: *const u8 = std::mem::transmute(self as *const Self);
91            std::slice::from_raw_parts(ptr, Self::len())
92        }
93    }
94    pub fn from_slice(buf: &[u8]) -> &Self {
95        assert!(buf.len() >= Self::len());
96        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
97        unsafe { std::mem::transmute(buf.as_ptr()) }
98    }
99    pub fn as_array(&self) -> &[u8; 4usize] {
100        unsafe { std::mem::transmute(self) }
101    }
102    pub fn from_array(buf: &[u8; 4usize]) -> &Self {
103        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
104        unsafe { std::mem::transmute(buf) }
105    }
106    pub fn into_array(self) -> [u8; 4usize] {
107        unsafe { std::mem::transmute(self) }
108    }
109    pub const fn len() -> usize {
110        const _: () = assert!(std::mem::size_of::<Rtgenmsg>() == 4usize);
111        4usize
112    }
113}
114impl std::fmt::Debug for Rtgenmsg {
115    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116        fmt.debug_struct("Rtgenmsg")
117            .field("family", &self.family)
118            .finish()
119    }
120}
121#[repr(C, packed(4))]
122pub struct FibRuleHdr {
123    pub family: u8,
124    pub dst_len: u8,
125    pub src_len: u8,
126    pub tos: u8,
127    pub table: u8,
128    pub _res1: [u8; 1usize],
129    pub _res2: [u8; 1usize],
130    #[doc = "Associated type: [`FrAct`] (enum)"]
131    pub action: u8,
132    pub flags: u32,
133}
134impl Clone for FibRuleHdr {
135    fn clone(&self) -> Self {
136        Self::new_from_array(*self.as_array())
137    }
138}
139#[doc = "Create zero-initialized struct"]
140impl Default for FibRuleHdr {
141    fn default() -> Self {
142        Self::new()
143    }
144}
145impl FibRuleHdr {
146    #[doc = "Create zero-initialized struct"]
147    pub fn new() -> Self {
148        Self::new_from_array([0u8; Self::len()])
149    }
150    #[doc = "Copy from contents from slice"]
151    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
152        if other.len() != Self::len() {
153            return None;
154        }
155        let mut buf = [0u8; Self::len()];
156        buf.clone_from_slice(other);
157        Some(Self::new_from_array(buf))
158    }
159    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
160    pub fn new_from_zeroed(other: &[u8]) -> Self {
161        let mut buf = [0u8; Self::len()];
162        let len = buf.len().min(other.len());
163        buf[..len].clone_from_slice(&other[..len]);
164        Self::new_from_array(buf)
165    }
166    pub fn new_from_array(buf: [u8; 12usize]) -> Self {
167        unsafe { std::mem::transmute(buf) }
168    }
169    pub fn as_slice(&self) -> &[u8] {
170        unsafe {
171            let ptr: *const u8 = std::mem::transmute(self as *const Self);
172            std::slice::from_raw_parts(ptr, Self::len())
173        }
174    }
175    pub fn from_slice(buf: &[u8]) -> &Self {
176        assert!(buf.len() >= Self::len());
177        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
178        unsafe { std::mem::transmute(buf.as_ptr()) }
179    }
180    pub fn as_array(&self) -> &[u8; 12usize] {
181        unsafe { std::mem::transmute(self) }
182    }
183    pub fn from_array(buf: &[u8; 12usize]) -> &Self {
184        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
185        unsafe { std::mem::transmute(buf) }
186    }
187    pub fn into_array(self) -> [u8; 12usize] {
188        unsafe { std::mem::transmute(self) }
189    }
190    pub const fn len() -> usize {
191        const _: () = assert!(std::mem::size_of::<FibRuleHdr>() == 12usize);
192        12usize
193    }
194}
195impl std::fmt::Debug for FibRuleHdr {
196    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197        fmt.debug_struct("FibRuleHdr")
198            .field("family", &self.family)
199            .field("dst_len", &self.dst_len)
200            .field("src_len", &self.src_len)
201            .field("tos", &self.tos)
202            .field("table", &self.table)
203            .field("action", &FormatEnum(self.action.into(), FrAct::from_value))
204            .field("flags", &self.flags)
205            .finish()
206    }
207}
208#[derive(Debug)]
209#[repr(C, packed(4))]
210pub struct FibRulePortRange {
211    pub start: u16,
212    pub end: u16,
213}
214impl Clone for FibRulePortRange {
215    fn clone(&self) -> Self {
216        Self::new_from_array(*self.as_array())
217    }
218}
219#[doc = "Create zero-initialized struct"]
220impl Default for FibRulePortRange {
221    fn default() -> Self {
222        Self::new()
223    }
224}
225impl FibRulePortRange {
226    #[doc = "Create zero-initialized struct"]
227    pub fn new() -> Self {
228        Self::new_from_array([0u8; Self::len()])
229    }
230    #[doc = "Copy from contents from slice"]
231    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
232        if other.len() != Self::len() {
233            return None;
234        }
235        let mut buf = [0u8; Self::len()];
236        buf.clone_from_slice(other);
237        Some(Self::new_from_array(buf))
238    }
239    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
240    pub fn new_from_zeroed(other: &[u8]) -> Self {
241        let mut buf = [0u8; Self::len()];
242        let len = buf.len().min(other.len());
243        buf[..len].clone_from_slice(&other[..len]);
244        Self::new_from_array(buf)
245    }
246    pub fn new_from_array(buf: [u8; 4usize]) -> Self {
247        unsafe { std::mem::transmute(buf) }
248    }
249    pub fn as_slice(&self) -> &[u8] {
250        unsafe {
251            let ptr: *const u8 = std::mem::transmute(self as *const Self);
252            std::slice::from_raw_parts(ptr, Self::len())
253        }
254    }
255    pub fn from_slice(buf: &[u8]) -> &Self {
256        assert!(buf.len() >= Self::len());
257        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
258        unsafe { std::mem::transmute(buf.as_ptr()) }
259    }
260    pub fn as_array(&self) -> &[u8; 4usize] {
261        unsafe { std::mem::transmute(self) }
262    }
263    pub fn from_array(buf: &[u8; 4usize]) -> &Self {
264        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
265        unsafe { std::mem::transmute(buf) }
266    }
267    pub fn into_array(self) -> [u8; 4usize] {
268        unsafe { std::mem::transmute(self) }
269    }
270    pub const fn len() -> usize {
271        const _: () = assert!(std::mem::size_of::<FibRulePortRange>() == 4usize);
272        4usize
273    }
274}
275#[derive(Debug)]
276#[repr(C, packed(4))]
277pub struct FibRuleUidRange {
278    pub start: u32,
279    pub end: u32,
280}
281impl Clone for FibRuleUidRange {
282    fn clone(&self) -> Self {
283        Self::new_from_array(*self.as_array())
284    }
285}
286#[doc = "Create zero-initialized struct"]
287impl Default for FibRuleUidRange {
288    fn default() -> Self {
289        Self::new()
290    }
291}
292impl FibRuleUidRange {
293    #[doc = "Create zero-initialized struct"]
294    pub fn new() -> Self {
295        Self::new_from_array([0u8; Self::len()])
296    }
297    #[doc = "Copy from contents from slice"]
298    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
299        if other.len() != Self::len() {
300            return None;
301        }
302        let mut buf = [0u8; Self::len()];
303        buf.clone_from_slice(other);
304        Some(Self::new_from_array(buf))
305    }
306    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
307    pub fn new_from_zeroed(other: &[u8]) -> Self {
308        let mut buf = [0u8; Self::len()];
309        let len = buf.len().min(other.len());
310        buf[..len].clone_from_slice(&other[..len]);
311        Self::new_from_array(buf)
312    }
313    pub fn new_from_array(buf: [u8; 8usize]) -> Self {
314        unsafe { std::mem::transmute(buf) }
315    }
316    pub fn as_slice(&self) -> &[u8] {
317        unsafe {
318            let ptr: *const u8 = std::mem::transmute(self as *const Self);
319            std::slice::from_raw_parts(ptr, Self::len())
320        }
321    }
322    pub fn from_slice(buf: &[u8]) -> &Self {
323        assert!(buf.len() >= Self::len());
324        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
325        unsafe { std::mem::transmute(buf.as_ptr()) }
326    }
327    pub fn as_array(&self) -> &[u8; 8usize] {
328        unsafe { std::mem::transmute(self) }
329    }
330    pub fn from_array(buf: &[u8; 8usize]) -> &Self {
331        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
332        unsafe { std::mem::transmute(buf) }
333    }
334    pub fn into_array(self) -> [u8; 8usize] {
335        unsafe { std::mem::transmute(self) }
336    }
337    pub const fn len() -> usize {
338        const _: () = assert!(std::mem::size_of::<FibRuleUidRange>() == 8usize);
339        8usize
340    }
341}
342#[derive(Clone)]
343pub enum FibRuleAttrs<'a> {
344    Dst(std::net::IpAddr),
345    Src(std::net::IpAddr),
346    Iifname(&'a CStr),
347    Goto(u32),
348    Unused2(&'a [u8]),
349    Priority(u32),
350    Unused3(&'a [u8]),
351    Unused4(&'a [u8]),
352    Unused5(&'a [u8]),
353    Fwmark(u32),
354    Flow(u32),
355    TunId(u64),
356    SuppressIfgroup(u32),
357    SuppressPrefixlen(u32),
358    Table(u32),
359    Fwmask(u32),
360    Oifname(&'a CStr),
361    Pad(&'a [u8]),
362    L3mdev(u8),
363    UidRange(FibRuleUidRange),
364    Protocol(u8),
365    IpProto(u8),
366    SportRange(FibRulePortRange),
367    DportRange(FibRulePortRange),
368    Dscp(u8),
369    Flowlabel(u32),
370    FlowlabelMask(u32),
371    SportMask(u16),
372    DportMask(u16),
373    DscpMask(u8),
374}
375impl<'a> IterableFibRuleAttrs<'a> {
376    pub fn get_dst(&self) -> Result<std::net::IpAddr, ErrorContext> {
377        let mut iter = self.clone();
378        iter.pos = 0;
379        for attr in iter {
380            if let FibRuleAttrs::Dst(val) = attr? {
381                return Ok(val);
382            }
383        }
384        Err(ErrorContext::new_missing(
385            "FibRuleAttrs",
386            "Dst",
387            self.orig_loc,
388            self.buf.as_ptr() as usize,
389        ))
390    }
391    pub fn get_src(&self) -> Result<std::net::IpAddr, ErrorContext> {
392        let mut iter = self.clone();
393        iter.pos = 0;
394        for attr in iter {
395            if let FibRuleAttrs::Src(val) = attr? {
396                return Ok(val);
397            }
398        }
399        Err(ErrorContext::new_missing(
400            "FibRuleAttrs",
401            "Src",
402            self.orig_loc,
403            self.buf.as_ptr() as usize,
404        ))
405    }
406    pub fn get_iifname(&self) -> Result<&'a CStr, ErrorContext> {
407        let mut iter = self.clone();
408        iter.pos = 0;
409        for attr in iter {
410            if let FibRuleAttrs::Iifname(val) = attr? {
411                return Ok(val);
412            }
413        }
414        Err(ErrorContext::new_missing(
415            "FibRuleAttrs",
416            "Iifname",
417            self.orig_loc,
418            self.buf.as_ptr() as usize,
419        ))
420    }
421    pub fn get_goto(&self) -> Result<u32, ErrorContext> {
422        let mut iter = self.clone();
423        iter.pos = 0;
424        for attr in iter {
425            if let FibRuleAttrs::Goto(val) = attr? {
426                return Ok(val);
427            }
428        }
429        Err(ErrorContext::new_missing(
430            "FibRuleAttrs",
431            "Goto",
432            self.orig_loc,
433            self.buf.as_ptr() as usize,
434        ))
435    }
436    pub fn get_unused2(&self) -> Result<&'a [u8], ErrorContext> {
437        let mut iter = self.clone();
438        iter.pos = 0;
439        for attr in iter {
440            if let FibRuleAttrs::Unused2(val) = attr? {
441                return Ok(val);
442            }
443        }
444        Err(ErrorContext::new_missing(
445            "FibRuleAttrs",
446            "Unused2",
447            self.orig_loc,
448            self.buf.as_ptr() as usize,
449        ))
450    }
451    pub fn get_priority(&self) -> Result<u32, ErrorContext> {
452        let mut iter = self.clone();
453        iter.pos = 0;
454        for attr in iter {
455            if let FibRuleAttrs::Priority(val) = attr? {
456                return Ok(val);
457            }
458        }
459        Err(ErrorContext::new_missing(
460            "FibRuleAttrs",
461            "Priority",
462            self.orig_loc,
463            self.buf.as_ptr() as usize,
464        ))
465    }
466    pub fn get_unused3(&self) -> Result<&'a [u8], ErrorContext> {
467        let mut iter = self.clone();
468        iter.pos = 0;
469        for attr in iter {
470            if let FibRuleAttrs::Unused3(val) = attr? {
471                return Ok(val);
472            }
473        }
474        Err(ErrorContext::new_missing(
475            "FibRuleAttrs",
476            "Unused3",
477            self.orig_loc,
478            self.buf.as_ptr() as usize,
479        ))
480    }
481    pub fn get_unused4(&self) -> Result<&'a [u8], ErrorContext> {
482        let mut iter = self.clone();
483        iter.pos = 0;
484        for attr in iter {
485            if let FibRuleAttrs::Unused4(val) = attr? {
486                return Ok(val);
487            }
488        }
489        Err(ErrorContext::new_missing(
490            "FibRuleAttrs",
491            "Unused4",
492            self.orig_loc,
493            self.buf.as_ptr() as usize,
494        ))
495    }
496    pub fn get_unused5(&self) -> Result<&'a [u8], ErrorContext> {
497        let mut iter = self.clone();
498        iter.pos = 0;
499        for attr in iter {
500            if let FibRuleAttrs::Unused5(val) = attr? {
501                return Ok(val);
502            }
503        }
504        Err(ErrorContext::new_missing(
505            "FibRuleAttrs",
506            "Unused5",
507            self.orig_loc,
508            self.buf.as_ptr() as usize,
509        ))
510    }
511    pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
512        let mut iter = self.clone();
513        iter.pos = 0;
514        for attr in iter {
515            if let FibRuleAttrs::Fwmark(val) = attr? {
516                return Ok(val);
517            }
518        }
519        Err(ErrorContext::new_missing(
520            "FibRuleAttrs",
521            "Fwmark",
522            self.orig_loc,
523            self.buf.as_ptr() as usize,
524        ))
525    }
526    pub fn get_flow(&self) -> Result<u32, ErrorContext> {
527        let mut iter = self.clone();
528        iter.pos = 0;
529        for attr in iter {
530            if let FibRuleAttrs::Flow(val) = attr? {
531                return Ok(val);
532            }
533        }
534        Err(ErrorContext::new_missing(
535            "FibRuleAttrs",
536            "Flow",
537            self.orig_loc,
538            self.buf.as_ptr() as usize,
539        ))
540    }
541    pub fn get_tun_id(&self) -> Result<u64, ErrorContext> {
542        let mut iter = self.clone();
543        iter.pos = 0;
544        for attr in iter {
545            if let FibRuleAttrs::TunId(val) = attr? {
546                return Ok(val);
547            }
548        }
549        Err(ErrorContext::new_missing(
550            "FibRuleAttrs",
551            "TunId",
552            self.orig_loc,
553            self.buf.as_ptr() as usize,
554        ))
555    }
556    pub fn get_suppress_ifgroup(&self) -> Result<u32, ErrorContext> {
557        let mut iter = self.clone();
558        iter.pos = 0;
559        for attr in iter {
560            if let FibRuleAttrs::SuppressIfgroup(val) = attr? {
561                return Ok(val);
562            }
563        }
564        Err(ErrorContext::new_missing(
565            "FibRuleAttrs",
566            "SuppressIfgroup",
567            self.orig_loc,
568            self.buf.as_ptr() as usize,
569        ))
570    }
571    pub fn get_suppress_prefixlen(&self) -> Result<u32, ErrorContext> {
572        let mut iter = self.clone();
573        iter.pos = 0;
574        for attr in iter {
575            if let FibRuleAttrs::SuppressPrefixlen(val) = attr? {
576                return Ok(val);
577            }
578        }
579        Err(ErrorContext::new_missing(
580            "FibRuleAttrs",
581            "SuppressPrefixlen",
582            self.orig_loc,
583            self.buf.as_ptr() as usize,
584        ))
585    }
586    pub fn get_table(&self) -> Result<u32, ErrorContext> {
587        let mut iter = self.clone();
588        iter.pos = 0;
589        for attr in iter {
590            if let FibRuleAttrs::Table(val) = attr? {
591                return Ok(val);
592            }
593        }
594        Err(ErrorContext::new_missing(
595            "FibRuleAttrs",
596            "Table",
597            self.orig_loc,
598            self.buf.as_ptr() as usize,
599        ))
600    }
601    pub fn get_fwmask(&self) -> Result<u32, ErrorContext> {
602        let mut iter = self.clone();
603        iter.pos = 0;
604        for attr in iter {
605            if let FibRuleAttrs::Fwmask(val) = attr? {
606                return Ok(val);
607            }
608        }
609        Err(ErrorContext::new_missing(
610            "FibRuleAttrs",
611            "Fwmask",
612            self.orig_loc,
613            self.buf.as_ptr() as usize,
614        ))
615    }
616    pub fn get_oifname(&self) -> Result<&'a CStr, ErrorContext> {
617        let mut iter = self.clone();
618        iter.pos = 0;
619        for attr in iter {
620            if let FibRuleAttrs::Oifname(val) = attr? {
621                return Ok(val);
622            }
623        }
624        Err(ErrorContext::new_missing(
625            "FibRuleAttrs",
626            "Oifname",
627            self.orig_loc,
628            self.buf.as_ptr() as usize,
629        ))
630    }
631    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
632        let mut iter = self.clone();
633        iter.pos = 0;
634        for attr in iter {
635            if let FibRuleAttrs::Pad(val) = attr? {
636                return Ok(val);
637            }
638        }
639        Err(ErrorContext::new_missing(
640            "FibRuleAttrs",
641            "Pad",
642            self.orig_loc,
643            self.buf.as_ptr() as usize,
644        ))
645    }
646    pub fn get_l3mdev(&self) -> Result<u8, ErrorContext> {
647        let mut iter = self.clone();
648        iter.pos = 0;
649        for attr in iter {
650            if let FibRuleAttrs::L3mdev(val) = attr? {
651                return Ok(val);
652            }
653        }
654        Err(ErrorContext::new_missing(
655            "FibRuleAttrs",
656            "L3mdev",
657            self.orig_loc,
658            self.buf.as_ptr() as usize,
659        ))
660    }
661    pub fn get_uid_range(&self) -> Result<FibRuleUidRange, ErrorContext> {
662        let mut iter = self.clone();
663        iter.pos = 0;
664        for attr in iter {
665            if let FibRuleAttrs::UidRange(val) = attr? {
666                return Ok(val);
667            }
668        }
669        Err(ErrorContext::new_missing(
670            "FibRuleAttrs",
671            "UidRange",
672            self.orig_loc,
673            self.buf.as_ptr() as usize,
674        ))
675    }
676    pub fn get_protocol(&self) -> Result<u8, ErrorContext> {
677        let mut iter = self.clone();
678        iter.pos = 0;
679        for attr in iter {
680            if let FibRuleAttrs::Protocol(val) = attr? {
681                return Ok(val);
682            }
683        }
684        Err(ErrorContext::new_missing(
685            "FibRuleAttrs",
686            "Protocol",
687            self.orig_loc,
688            self.buf.as_ptr() as usize,
689        ))
690    }
691    pub fn get_ip_proto(&self) -> Result<u8, ErrorContext> {
692        let mut iter = self.clone();
693        iter.pos = 0;
694        for attr in iter {
695            if let FibRuleAttrs::IpProto(val) = attr? {
696                return Ok(val);
697            }
698        }
699        Err(ErrorContext::new_missing(
700            "FibRuleAttrs",
701            "IpProto",
702            self.orig_loc,
703            self.buf.as_ptr() as usize,
704        ))
705    }
706    pub fn get_sport_range(&self) -> Result<FibRulePortRange, ErrorContext> {
707        let mut iter = self.clone();
708        iter.pos = 0;
709        for attr in iter {
710            if let FibRuleAttrs::SportRange(val) = attr? {
711                return Ok(val);
712            }
713        }
714        Err(ErrorContext::new_missing(
715            "FibRuleAttrs",
716            "SportRange",
717            self.orig_loc,
718            self.buf.as_ptr() as usize,
719        ))
720    }
721    pub fn get_dport_range(&self) -> Result<FibRulePortRange, ErrorContext> {
722        let mut iter = self.clone();
723        iter.pos = 0;
724        for attr in iter {
725            if let FibRuleAttrs::DportRange(val) = attr? {
726                return Ok(val);
727            }
728        }
729        Err(ErrorContext::new_missing(
730            "FibRuleAttrs",
731            "DportRange",
732            self.orig_loc,
733            self.buf.as_ptr() as usize,
734        ))
735    }
736    pub fn get_dscp(&self) -> Result<u8, ErrorContext> {
737        let mut iter = self.clone();
738        iter.pos = 0;
739        for attr in iter {
740            if let FibRuleAttrs::Dscp(val) = attr? {
741                return Ok(val);
742            }
743        }
744        Err(ErrorContext::new_missing(
745            "FibRuleAttrs",
746            "Dscp",
747            self.orig_loc,
748            self.buf.as_ptr() as usize,
749        ))
750    }
751    pub fn get_flowlabel(&self) -> Result<u32, ErrorContext> {
752        let mut iter = self.clone();
753        iter.pos = 0;
754        for attr in iter {
755            if let FibRuleAttrs::Flowlabel(val) = attr? {
756                return Ok(val);
757            }
758        }
759        Err(ErrorContext::new_missing(
760            "FibRuleAttrs",
761            "Flowlabel",
762            self.orig_loc,
763            self.buf.as_ptr() as usize,
764        ))
765    }
766    pub fn get_flowlabel_mask(&self) -> Result<u32, ErrorContext> {
767        let mut iter = self.clone();
768        iter.pos = 0;
769        for attr in iter {
770            if let FibRuleAttrs::FlowlabelMask(val) = attr? {
771                return Ok(val);
772            }
773        }
774        Err(ErrorContext::new_missing(
775            "FibRuleAttrs",
776            "FlowlabelMask",
777            self.orig_loc,
778            self.buf.as_ptr() as usize,
779        ))
780    }
781    pub fn get_sport_mask(&self) -> Result<u16, ErrorContext> {
782        let mut iter = self.clone();
783        iter.pos = 0;
784        for attr in iter {
785            if let FibRuleAttrs::SportMask(val) = attr? {
786                return Ok(val);
787            }
788        }
789        Err(ErrorContext::new_missing(
790            "FibRuleAttrs",
791            "SportMask",
792            self.orig_loc,
793            self.buf.as_ptr() as usize,
794        ))
795    }
796    pub fn get_dport_mask(&self) -> Result<u16, ErrorContext> {
797        let mut iter = self.clone();
798        iter.pos = 0;
799        for attr in iter {
800            if let FibRuleAttrs::DportMask(val) = attr? {
801                return Ok(val);
802            }
803        }
804        Err(ErrorContext::new_missing(
805            "FibRuleAttrs",
806            "DportMask",
807            self.orig_loc,
808            self.buf.as_ptr() as usize,
809        ))
810    }
811    pub fn get_dscp_mask(&self) -> Result<u8, ErrorContext> {
812        let mut iter = self.clone();
813        iter.pos = 0;
814        for attr in iter {
815            if let FibRuleAttrs::DscpMask(val) = attr? {
816                return Ok(val);
817            }
818        }
819        Err(ErrorContext::new_missing(
820            "FibRuleAttrs",
821            "DscpMask",
822            self.orig_loc,
823            self.buf.as_ptr() as usize,
824        ))
825    }
826}
827impl FibRuleAttrs<'_> {
828    pub fn new<'a>(buf: &'a [u8]) -> IterableFibRuleAttrs<'a> {
829        IterableFibRuleAttrs::with_loc(buf, buf.as_ptr() as usize)
830    }
831    fn attr_from_type(r#type: u16) -> Option<&'static str> {
832        let res = match r#type {
833            1u16 => "Dst",
834            2u16 => "Src",
835            3u16 => "Iifname",
836            4u16 => "Goto",
837            5u16 => "Unused2",
838            6u16 => "Priority",
839            7u16 => "Unused3",
840            8u16 => "Unused4",
841            9u16 => "Unused5",
842            10u16 => "Fwmark",
843            11u16 => "Flow",
844            12u16 => "TunId",
845            13u16 => "SuppressIfgroup",
846            14u16 => "SuppressPrefixlen",
847            15u16 => "Table",
848            16u16 => "Fwmask",
849            17u16 => "Oifname",
850            18u16 => "Pad",
851            19u16 => "L3mdev",
852            20u16 => "UidRange",
853            21u16 => "Protocol",
854            22u16 => "IpProto",
855            23u16 => "SportRange",
856            24u16 => "DportRange",
857            25u16 => "Dscp",
858            26u16 => "Flowlabel",
859            27u16 => "FlowlabelMask",
860            28u16 => "SportMask",
861            29u16 => "DportMask",
862            30u16 => "DscpMask",
863            _ => return None,
864        };
865        Some(res)
866    }
867}
868#[derive(Clone, Copy, Default)]
869pub struct IterableFibRuleAttrs<'a> {
870    buf: &'a [u8],
871    pos: usize,
872    orig_loc: usize,
873}
874impl<'a> IterableFibRuleAttrs<'a> {
875    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
876        Self {
877            buf,
878            pos: 0,
879            orig_loc,
880        }
881    }
882    pub fn get_buf(&self) -> &'a [u8] {
883        self.buf
884    }
885}
886impl<'a> Iterator for IterableFibRuleAttrs<'a> {
887    type Item = Result<FibRuleAttrs<'a>, ErrorContext>;
888    fn next(&mut self) -> Option<Self::Item> {
889        let pos = self.pos;
890        let mut r#type;
891        loop {
892            r#type = None;
893            if self.buf.len() == self.pos {
894                return None;
895            }
896            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
897                break;
898            };
899            r#type = Some(header.r#type);
900            let res = match header.r#type {
901                1u16 => FibRuleAttrs::Dst({
902                    let res = parse_ip(next);
903                    let Some(val) = res else { break };
904                    val
905                }),
906                2u16 => FibRuleAttrs::Src({
907                    let res = parse_ip(next);
908                    let Some(val) = res else { break };
909                    val
910                }),
911                3u16 => FibRuleAttrs::Iifname({
912                    let res = CStr::from_bytes_with_nul(next).ok();
913                    let Some(val) = res else { break };
914                    val
915                }),
916                4u16 => FibRuleAttrs::Goto({
917                    let res = parse_u32(next);
918                    let Some(val) = res else { break };
919                    val
920                }),
921                5u16 => FibRuleAttrs::Unused2({
922                    let res = Some(next);
923                    let Some(val) = res else { break };
924                    val
925                }),
926                6u16 => FibRuleAttrs::Priority({
927                    let res = parse_u32(next);
928                    let Some(val) = res else { break };
929                    val
930                }),
931                7u16 => FibRuleAttrs::Unused3({
932                    let res = Some(next);
933                    let Some(val) = res else { break };
934                    val
935                }),
936                8u16 => FibRuleAttrs::Unused4({
937                    let res = Some(next);
938                    let Some(val) = res else { break };
939                    val
940                }),
941                9u16 => FibRuleAttrs::Unused5({
942                    let res = Some(next);
943                    let Some(val) = res else { break };
944                    val
945                }),
946                10u16 => FibRuleAttrs::Fwmark({
947                    let res = parse_u32(next);
948                    let Some(val) = res else { break };
949                    val
950                }),
951                11u16 => FibRuleAttrs::Flow({
952                    let res = parse_u32(next);
953                    let Some(val) = res else { break };
954                    val
955                }),
956                12u16 => FibRuleAttrs::TunId({
957                    let res = parse_u64(next);
958                    let Some(val) = res else { break };
959                    val
960                }),
961                13u16 => FibRuleAttrs::SuppressIfgroup({
962                    let res = parse_u32(next);
963                    let Some(val) = res else { break };
964                    val
965                }),
966                14u16 => FibRuleAttrs::SuppressPrefixlen({
967                    let res = parse_u32(next);
968                    let Some(val) = res else { break };
969                    val
970                }),
971                15u16 => FibRuleAttrs::Table({
972                    let res = parse_u32(next);
973                    let Some(val) = res else { break };
974                    val
975                }),
976                16u16 => FibRuleAttrs::Fwmask({
977                    let res = parse_u32(next);
978                    let Some(val) = res else { break };
979                    val
980                }),
981                17u16 => FibRuleAttrs::Oifname({
982                    let res = CStr::from_bytes_with_nul(next).ok();
983                    let Some(val) = res else { break };
984                    val
985                }),
986                18u16 => FibRuleAttrs::Pad({
987                    let res = Some(next);
988                    let Some(val) = res else { break };
989                    val
990                }),
991                19u16 => FibRuleAttrs::L3mdev({
992                    let res = parse_u8(next);
993                    let Some(val) = res else { break };
994                    val
995                }),
996                20u16 => FibRuleAttrs::UidRange({
997                    let res = Some(FibRuleUidRange::new_from_zeroed(next));
998                    let Some(val) = res else { break };
999                    val
1000                }),
1001                21u16 => FibRuleAttrs::Protocol({
1002                    let res = parse_u8(next);
1003                    let Some(val) = res else { break };
1004                    val
1005                }),
1006                22u16 => FibRuleAttrs::IpProto({
1007                    let res = parse_u8(next);
1008                    let Some(val) = res else { break };
1009                    val
1010                }),
1011                23u16 => FibRuleAttrs::SportRange({
1012                    let res = Some(FibRulePortRange::new_from_zeroed(next));
1013                    let Some(val) = res else { break };
1014                    val
1015                }),
1016                24u16 => FibRuleAttrs::DportRange({
1017                    let res = Some(FibRulePortRange::new_from_zeroed(next));
1018                    let Some(val) = res else { break };
1019                    val
1020                }),
1021                25u16 => FibRuleAttrs::Dscp({
1022                    let res = parse_u8(next);
1023                    let Some(val) = res else { break };
1024                    val
1025                }),
1026                26u16 => FibRuleAttrs::Flowlabel({
1027                    let res = parse_be_u32(next);
1028                    let Some(val) = res else { break };
1029                    val
1030                }),
1031                27u16 => FibRuleAttrs::FlowlabelMask({
1032                    let res = parse_be_u32(next);
1033                    let Some(val) = res else { break };
1034                    val
1035                }),
1036                28u16 => FibRuleAttrs::SportMask({
1037                    let res = parse_u16(next);
1038                    let Some(val) = res else { break };
1039                    val
1040                }),
1041                29u16 => FibRuleAttrs::DportMask({
1042                    let res = parse_u16(next);
1043                    let Some(val) = res else { break };
1044                    val
1045                }),
1046                30u16 => FibRuleAttrs::DscpMask({
1047                    let res = parse_u8(next);
1048                    let Some(val) = res else { break };
1049                    val
1050                }),
1051                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1052                n => continue,
1053            };
1054            return Some(Ok(res));
1055        }
1056        Some(Err(ErrorContext::new(
1057            "FibRuleAttrs",
1058            r#type.and_then(|t| FibRuleAttrs::attr_from_type(t)),
1059            self.orig_loc,
1060            self.buf.as_ptr().wrapping_add(pos) as usize,
1061        )))
1062    }
1063}
1064impl<'a> std::fmt::Debug for IterableFibRuleAttrs<'_> {
1065    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1066        let mut fmt = f.debug_struct("FibRuleAttrs");
1067        for attr in self.clone() {
1068            let attr = match attr {
1069                Ok(a) => a,
1070                Err(err) => {
1071                    fmt.finish()?;
1072                    f.write_str("Err(")?;
1073                    err.fmt(f)?;
1074                    return f.write_str(")");
1075                }
1076            };
1077            match attr {
1078                FibRuleAttrs::Dst(val) => fmt.field("Dst", &val),
1079                FibRuleAttrs::Src(val) => fmt.field("Src", &val),
1080                FibRuleAttrs::Iifname(val) => fmt.field("Iifname", &val),
1081                FibRuleAttrs::Goto(val) => fmt.field("Goto", &val),
1082                FibRuleAttrs::Unused2(val) => fmt.field("Unused2", &val),
1083                FibRuleAttrs::Priority(val) => fmt.field("Priority", &val),
1084                FibRuleAttrs::Unused3(val) => fmt.field("Unused3", &val),
1085                FibRuleAttrs::Unused4(val) => fmt.field("Unused4", &val),
1086                FibRuleAttrs::Unused5(val) => fmt.field("Unused5", &val),
1087                FibRuleAttrs::Fwmark(val) => fmt.field("Fwmark", &val),
1088                FibRuleAttrs::Flow(val) => fmt.field("Flow", &val),
1089                FibRuleAttrs::TunId(val) => fmt.field("TunId", &val),
1090                FibRuleAttrs::SuppressIfgroup(val) => fmt.field("SuppressIfgroup", &val),
1091                FibRuleAttrs::SuppressPrefixlen(val) => fmt.field("SuppressPrefixlen", &val),
1092                FibRuleAttrs::Table(val) => fmt.field("Table", &val),
1093                FibRuleAttrs::Fwmask(val) => fmt.field("Fwmask", &val),
1094                FibRuleAttrs::Oifname(val) => fmt.field("Oifname", &val),
1095                FibRuleAttrs::Pad(val) => fmt.field("Pad", &val),
1096                FibRuleAttrs::L3mdev(val) => fmt.field("L3mdev", &val),
1097                FibRuleAttrs::UidRange(val) => fmt.field("UidRange", &val),
1098                FibRuleAttrs::Protocol(val) => fmt.field("Protocol", &val),
1099                FibRuleAttrs::IpProto(val) => fmt.field("IpProto", &val),
1100                FibRuleAttrs::SportRange(val) => fmt.field("SportRange", &val),
1101                FibRuleAttrs::DportRange(val) => fmt.field("DportRange", &val),
1102                FibRuleAttrs::Dscp(val) => fmt.field("Dscp", &val),
1103                FibRuleAttrs::Flowlabel(val) => fmt.field("Flowlabel", &val),
1104                FibRuleAttrs::FlowlabelMask(val) => fmt.field("FlowlabelMask", &val),
1105                FibRuleAttrs::SportMask(val) => fmt.field("SportMask", &val),
1106                FibRuleAttrs::DportMask(val) => fmt.field("DportMask", &val),
1107                FibRuleAttrs::DscpMask(val) => fmt.field("DscpMask", &val),
1108            };
1109        }
1110        fmt.finish()
1111    }
1112}
1113impl IterableFibRuleAttrs<'_> {
1114    pub fn lookup_attr(
1115        &self,
1116        offset: usize,
1117        missing_type: Option<u16>,
1118    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1119        let mut stack = Vec::new();
1120        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1121        if missing_type.is_some() && cur == offset {
1122            stack.push(("FibRuleAttrs", offset));
1123            return (
1124                stack,
1125                missing_type.and_then(|t| FibRuleAttrs::attr_from_type(t)),
1126            );
1127        }
1128        if cur > offset || cur + self.buf.len() < offset {
1129            return (stack, None);
1130        }
1131        let mut attrs = self.clone();
1132        let mut last_off = cur + attrs.pos;
1133        while let Some(attr) = attrs.next() {
1134            let Ok(attr) = attr else { break };
1135            match attr {
1136                FibRuleAttrs::Dst(val) => {
1137                    if last_off == offset {
1138                        stack.push(("Dst", last_off));
1139                        break;
1140                    }
1141                }
1142                FibRuleAttrs::Src(val) => {
1143                    if last_off == offset {
1144                        stack.push(("Src", last_off));
1145                        break;
1146                    }
1147                }
1148                FibRuleAttrs::Iifname(val) => {
1149                    if last_off == offset {
1150                        stack.push(("Iifname", last_off));
1151                        break;
1152                    }
1153                }
1154                FibRuleAttrs::Goto(val) => {
1155                    if last_off == offset {
1156                        stack.push(("Goto", last_off));
1157                        break;
1158                    }
1159                }
1160                FibRuleAttrs::Unused2(val) => {
1161                    if last_off == offset {
1162                        stack.push(("Unused2", last_off));
1163                        break;
1164                    }
1165                }
1166                FibRuleAttrs::Priority(val) => {
1167                    if last_off == offset {
1168                        stack.push(("Priority", last_off));
1169                        break;
1170                    }
1171                }
1172                FibRuleAttrs::Unused3(val) => {
1173                    if last_off == offset {
1174                        stack.push(("Unused3", last_off));
1175                        break;
1176                    }
1177                }
1178                FibRuleAttrs::Unused4(val) => {
1179                    if last_off == offset {
1180                        stack.push(("Unused4", last_off));
1181                        break;
1182                    }
1183                }
1184                FibRuleAttrs::Unused5(val) => {
1185                    if last_off == offset {
1186                        stack.push(("Unused5", last_off));
1187                        break;
1188                    }
1189                }
1190                FibRuleAttrs::Fwmark(val) => {
1191                    if last_off == offset {
1192                        stack.push(("Fwmark", last_off));
1193                        break;
1194                    }
1195                }
1196                FibRuleAttrs::Flow(val) => {
1197                    if last_off == offset {
1198                        stack.push(("Flow", last_off));
1199                        break;
1200                    }
1201                }
1202                FibRuleAttrs::TunId(val) => {
1203                    if last_off == offset {
1204                        stack.push(("TunId", last_off));
1205                        break;
1206                    }
1207                }
1208                FibRuleAttrs::SuppressIfgroup(val) => {
1209                    if last_off == offset {
1210                        stack.push(("SuppressIfgroup", last_off));
1211                        break;
1212                    }
1213                }
1214                FibRuleAttrs::SuppressPrefixlen(val) => {
1215                    if last_off == offset {
1216                        stack.push(("SuppressPrefixlen", last_off));
1217                        break;
1218                    }
1219                }
1220                FibRuleAttrs::Table(val) => {
1221                    if last_off == offset {
1222                        stack.push(("Table", last_off));
1223                        break;
1224                    }
1225                }
1226                FibRuleAttrs::Fwmask(val) => {
1227                    if last_off == offset {
1228                        stack.push(("Fwmask", last_off));
1229                        break;
1230                    }
1231                }
1232                FibRuleAttrs::Oifname(val) => {
1233                    if last_off == offset {
1234                        stack.push(("Oifname", last_off));
1235                        break;
1236                    }
1237                }
1238                FibRuleAttrs::Pad(val) => {
1239                    if last_off == offset {
1240                        stack.push(("Pad", last_off));
1241                        break;
1242                    }
1243                }
1244                FibRuleAttrs::L3mdev(val) => {
1245                    if last_off == offset {
1246                        stack.push(("L3mdev", last_off));
1247                        break;
1248                    }
1249                }
1250                FibRuleAttrs::UidRange(val) => {
1251                    if last_off == offset {
1252                        stack.push(("UidRange", last_off));
1253                        break;
1254                    }
1255                }
1256                FibRuleAttrs::Protocol(val) => {
1257                    if last_off == offset {
1258                        stack.push(("Protocol", last_off));
1259                        break;
1260                    }
1261                }
1262                FibRuleAttrs::IpProto(val) => {
1263                    if last_off == offset {
1264                        stack.push(("IpProto", last_off));
1265                        break;
1266                    }
1267                }
1268                FibRuleAttrs::SportRange(val) => {
1269                    if last_off == offset {
1270                        stack.push(("SportRange", last_off));
1271                        break;
1272                    }
1273                }
1274                FibRuleAttrs::DportRange(val) => {
1275                    if last_off == offset {
1276                        stack.push(("DportRange", last_off));
1277                        break;
1278                    }
1279                }
1280                FibRuleAttrs::Dscp(val) => {
1281                    if last_off == offset {
1282                        stack.push(("Dscp", last_off));
1283                        break;
1284                    }
1285                }
1286                FibRuleAttrs::Flowlabel(val) => {
1287                    if last_off == offset {
1288                        stack.push(("Flowlabel", last_off));
1289                        break;
1290                    }
1291                }
1292                FibRuleAttrs::FlowlabelMask(val) => {
1293                    if last_off == offset {
1294                        stack.push(("FlowlabelMask", last_off));
1295                        break;
1296                    }
1297                }
1298                FibRuleAttrs::SportMask(val) => {
1299                    if last_off == offset {
1300                        stack.push(("SportMask", last_off));
1301                        break;
1302                    }
1303                }
1304                FibRuleAttrs::DportMask(val) => {
1305                    if last_off == offset {
1306                        stack.push(("DportMask", last_off));
1307                        break;
1308                    }
1309                }
1310                FibRuleAttrs::DscpMask(val) => {
1311                    if last_off == offset {
1312                        stack.push(("DscpMask", last_off));
1313                        break;
1314                    }
1315                }
1316                _ => {}
1317            };
1318            last_off = cur + attrs.pos;
1319        }
1320        if !stack.is_empty() {
1321            stack.push(("FibRuleAttrs", cur));
1322        }
1323        (stack, None)
1324    }
1325}
1326pub struct PushFibRuleAttrs<Prev: Rec> {
1327    pub(crate) prev: Option<Prev>,
1328    pub(crate) header_offset: Option<usize>,
1329}
1330impl<Prev: Rec> Rec for PushFibRuleAttrs<Prev> {
1331    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1332        self.prev.as_mut().unwrap().as_rec_mut()
1333    }
1334    fn as_rec(&self) -> &Vec<u8> {
1335        self.prev.as_ref().unwrap().as_rec()
1336    }
1337}
1338impl<Prev: Rec> PushFibRuleAttrs<Prev> {
1339    pub fn new(prev: Prev) -> Self {
1340        Self {
1341            prev: Some(prev),
1342            header_offset: None,
1343        }
1344    }
1345    pub fn end_nested(mut self) -> Prev {
1346        let mut prev = self.prev.take().unwrap();
1347        if let Some(header_offset) = &self.header_offset {
1348            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1349        }
1350        prev
1351    }
1352    pub fn push_dst(mut self, value: std::net::IpAddr) -> Self {
1353        push_header(self.as_rec_mut(), 1u16, {
1354            match &value {
1355                IpAddr::V4(_) => 4,
1356                IpAddr::V6(_) => 16,
1357            }
1358        } as u16);
1359        encode_ip(self.as_rec_mut(), value);
1360        self
1361    }
1362    pub fn push_src(mut self, value: std::net::IpAddr) -> Self {
1363        push_header(self.as_rec_mut(), 2u16, {
1364            match &value {
1365                IpAddr::V4(_) => 4,
1366                IpAddr::V6(_) => 16,
1367            }
1368        } as u16);
1369        encode_ip(self.as_rec_mut(), value);
1370        self
1371    }
1372    pub fn push_iifname(mut self, value: &CStr) -> Self {
1373        push_header(
1374            self.as_rec_mut(),
1375            3u16,
1376            value.to_bytes_with_nul().len() as u16,
1377        );
1378        self.as_rec_mut().extend(value.to_bytes_with_nul());
1379        self
1380    }
1381    pub fn push_iifname_bytes(mut self, value: &[u8]) -> Self {
1382        push_header(self.as_rec_mut(), 3u16, (value.len() + 1) as u16);
1383        self.as_rec_mut().extend(value);
1384        self.as_rec_mut().push(0);
1385        self
1386    }
1387    pub fn push_goto(mut self, value: u32) -> Self {
1388        push_header(self.as_rec_mut(), 4u16, 4 as u16);
1389        self.as_rec_mut().extend(value.to_ne_bytes());
1390        self
1391    }
1392    pub fn push_unused2(mut self, value: &[u8]) -> Self {
1393        push_header(self.as_rec_mut(), 5u16, value.len() as u16);
1394        self.as_rec_mut().extend(value);
1395        self
1396    }
1397    pub fn push_priority(mut self, value: u32) -> Self {
1398        push_header(self.as_rec_mut(), 6u16, 4 as u16);
1399        self.as_rec_mut().extend(value.to_ne_bytes());
1400        self
1401    }
1402    pub fn push_unused3(mut self, value: &[u8]) -> Self {
1403        push_header(self.as_rec_mut(), 7u16, value.len() as u16);
1404        self.as_rec_mut().extend(value);
1405        self
1406    }
1407    pub fn push_unused4(mut self, value: &[u8]) -> Self {
1408        push_header(self.as_rec_mut(), 8u16, value.len() as u16);
1409        self.as_rec_mut().extend(value);
1410        self
1411    }
1412    pub fn push_unused5(mut self, value: &[u8]) -> Self {
1413        push_header(self.as_rec_mut(), 9u16, value.len() as u16);
1414        self.as_rec_mut().extend(value);
1415        self
1416    }
1417    pub fn push_fwmark(mut self, value: u32) -> Self {
1418        push_header(self.as_rec_mut(), 10u16, 4 as u16);
1419        self.as_rec_mut().extend(value.to_ne_bytes());
1420        self
1421    }
1422    pub fn push_flow(mut self, value: u32) -> Self {
1423        push_header(self.as_rec_mut(), 11u16, 4 as u16);
1424        self.as_rec_mut().extend(value.to_ne_bytes());
1425        self
1426    }
1427    pub fn push_tun_id(mut self, value: u64) -> Self {
1428        push_header(self.as_rec_mut(), 12u16, 8 as u16);
1429        self.as_rec_mut().extend(value.to_ne_bytes());
1430        self
1431    }
1432    pub fn push_suppress_ifgroup(mut self, value: u32) -> Self {
1433        push_header(self.as_rec_mut(), 13u16, 4 as u16);
1434        self.as_rec_mut().extend(value.to_ne_bytes());
1435        self
1436    }
1437    pub fn push_suppress_prefixlen(mut self, value: u32) -> Self {
1438        push_header(self.as_rec_mut(), 14u16, 4 as u16);
1439        self.as_rec_mut().extend(value.to_ne_bytes());
1440        self
1441    }
1442    pub fn push_table(mut self, value: u32) -> Self {
1443        push_header(self.as_rec_mut(), 15u16, 4 as u16);
1444        self.as_rec_mut().extend(value.to_ne_bytes());
1445        self
1446    }
1447    pub fn push_fwmask(mut self, value: u32) -> Self {
1448        push_header(self.as_rec_mut(), 16u16, 4 as u16);
1449        self.as_rec_mut().extend(value.to_ne_bytes());
1450        self
1451    }
1452    pub fn push_oifname(mut self, value: &CStr) -> Self {
1453        push_header(
1454            self.as_rec_mut(),
1455            17u16,
1456            value.to_bytes_with_nul().len() as u16,
1457        );
1458        self.as_rec_mut().extend(value.to_bytes_with_nul());
1459        self
1460    }
1461    pub fn push_oifname_bytes(mut self, value: &[u8]) -> Self {
1462        push_header(self.as_rec_mut(), 17u16, (value.len() + 1) as u16);
1463        self.as_rec_mut().extend(value);
1464        self.as_rec_mut().push(0);
1465        self
1466    }
1467    pub fn push_pad(mut self, value: &[u8]) -> Self {
1468        push_header(self.as_rec_mut(), 18u16, value.len() as u16);
1469        self.as_rec_mut().extend(value);
1470        self
1471    }
1472    pub fn push_l3mdev(mut self, value: u8) -> Self {
1473        push_header(self.as_rec_mut(), 19u16, 1 as u16);
1474        self.as_rec_mut().extend(value.to_ne_bytes());
1475        self
1476    }
1477    pub fn push_uid_range(mut self, value: FibRuleUidRange) -> Self {
1478        push_header(self.as_rec_mut(), 20u16, value.as_slice().len() as u16);
1479        self.as_rec_mut().extend(value.as_slice());
1480        self
1481    }
1482    pub fn push_protocol(mut self, value: u8) -> Self {
1483        push_header(self.as_rec_mut(), 21u16, 1 as u16);
1484        self.as_rec_mut().extend(value.to_ne_bytes());
1485        self
1486    }
1487    pub fn push_ip_proto(mut self, value: u8) -> Self {
1488        push_header(self.as_rec_mut(), 22u16, 1 as u16);
1489        self.as_rec_mut().extend(value.to_ne_bytes());
1490        self
1491    }
1492    pub fn push_sport_range(mut self, value: FibRulePortRange) -> Self {
1493        push_header(self.as_rec_mut(), 23u16, value.as_slice().len() as u16);
1494        self.as_rec_mut().extend(value.as_slice());
1495        self
1496    }
1497    pub fn push_dport_range(mut self, value: FibRulePortRange) -> Self {
1498        push_header(self.as_rec_mut(), 24u16, value.as_slice().len() as u16);
1499        self.as_rec_mut().extend(value.as_slice());
1500        self
1501    }
1502    pub fn push_dscp(mut self, value: u8) -> Self {
1503        push_header(self.as_rec_mut(), 25u16, 1 as u16);
1504        self.as_rec_mut().extend(value.to_ne_bytes());
1505        self
1506    }
1507    pub fn push_flowlabel(mut self, value: u32) -> Self {
1508        push_header(self.as_rec_mut(), 26u16, 4 as u16);
1509        self.as_rec_mut().extend(value.to_be_bytes());
1510        self
1511    }
1512    pub fn push_flowlabel_mask(mut self, value: u32) -> Self {
1513        push_header(self.as_rec_mut(), 27u16, 4 as u16);
1514        self.as_rec_mut().extend(value.to_be_bytes());
1515        self
1516    }
1517    pub fn push_sport_mask(mut self, value: u16) -> Self {
1518        push_header(self.as_rec_mut(), 28u16, 2 as u16);
1519        self.as_rec_mut().extend(value.to_ne_bytes());
1520        self
1521    }
1522    pub fn push_dport_mask(mut self, value: u16) -> Self {
1523        push_header(self.as_rec_mut(), 29u16, 2 as u16);
1524        self.as_rec_mut().extend(value.to_ne_bytes());
1525        self
1526    }
1527    pub fn push_dscp_mask(mut self, value: u8) -> Self {
1528        push_header(self.as_rec_mut(), 30u16, 1 as u16);
1529        self.as_rec_mut().extend(value.to_ne_bytes());
1530        self
1531    }
1532}
1533impl<Prev: Rec> Drop for PushFibRuleAttrs<Prev> {
1534    fn drop(&mut self) {
1535        if let Some(prev) = &mut self.prev {
1536            if let Some(header_offset) = &self.header_offset {
1537                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1538            }
1539        }
1540    }
1541}
1542#[doc = "Add new FIB rule\nRequest attributes:\n- [.push_iifname()](PushFibRuleAttrs::push_iifname)\n- [.push_goto()](PushFibRuleAttrs::push_goto)\n- [.push_priority()](PushFibRuleAttrs::push_priority)\n- [.push_fwmark()](PushFibRuleAttrs::push_fwmark)\n- [.push_flow()](PushFibRuleAttrs::push_flow)\n- [.push_tun_id()](PushFibRuleAttrs::push_tun_id)\n- [.push_suppress_ifgroup()](PushFibRuleAttrs::push_suppress_ifgroup)\n- [.push_suppress_prefixlen()](PushFibRuleAttrs::push_suppress_prefixlen)\n- [.push_table()](PushFibRuleAttrs::push_table)\n- [.push_fwmask()](PushFibRuleAttrs::push_fwmask)\n- [.push_oifname()](PushFibRuleAttrs::push_oifname)\n- [.push_l3mdev()](PushFibRuleAttrs::push_l3mdev)\n- [.push_uid_range()](PushFibRuleAttrs::push_uid_range)\n- [.push_protocol()](PushFibRuleAttrs::push_protocol)\n- [.push_ip_proto()](PushFibRuleAttrs::push_ip_proto)\n- [.push_sport_range()](PushFibRuleAttrs::push_sport_range)\n- [.push_dport_range()](PushFibRuleAttrs::push_dport_range)\n- [.push_dscp()](PushFibRuleAttrs::push_dscp)\n- [.push_flowlabel()](PushFibRuleAttrs::push_flowlabel)\n- [.push_flowlabel_mask()](PushFibRuleAttrs::push_flowlabel_mask)\n- [.push_sport_mask()](PushFibRuleAttrs::push_sport_mask)\n- [.push_dport_mask()](PushFibRuleAttrs::push_dport_mask)\n- [.push_dscp_mask()](PushFibRuleAttrs::push_dscp_mask)\n"]
1543#[derive(Debug)]
1544pub struct OpNewruleDo<'r> {
1545    request: Request<'r>,
1546}
1547impl<'r> OpNewruleDo<'r> {
1548    pub fn new(mut request: Request<'r>, header: &FibRuleHdr) -> Self {
1549        Self::write_header(request.buf_mut(), header);
1550        Self { request: request }
1551    }
1552    pub fn encode_request<'buf>(
1553        buf: &'buf mut Vec<u8>,
1554        header: &FibRuleHdr,
1555    ) -> PushFibRuleAttrs<&'buf mut Vec<u8>> {
1556        Self::write_header(buf, header);
1557        PushFibRuleAttrs::new(buf)
1558    }
1559    pub fn encode(&mut self) -> PushFibRuleAttrs<&mut Vec<u8>> {
1560        PushFibRuleAttrs::new(self.request.buf_mut())
1561    }
1562    pub fn into_encoder(self) -> PushFibRuleAttrs<RequestBuf<'r>> {
1563        PushFibRuleAttrs::new(self.request.buf)
1564    }
1565    pub fn decode_request<'a>(buf: &'a [u8]) -> (FibRuleHdr, IterableFibRuleAttrs<'a>) {
1566        let (header, attrs) = buf.split_at(buf.len().min(FibRuleHdr::len()));
1567        (
1568            FibRuleHdr::new_from_slice(header).unwrap_or_default(),
1569            IterableFibRuleAttrs::with_loc(attrs, buf.as_ptr() as usize),
1570        )
1571    }
1572    fn write_header<Prev: Rec>(prev: &mut Prev, header: &FibRuleHdr) {
1573        prev.as_rec_mut().extend(header.as_slice());
1574    }
1575}
1576impl NetlinkRequest for OpNewruleDo<'_> {
1577    fn protocol(&self) -> Protocol {
1578        Protocol::Raw {
1579            protonum: 0u16,
1580            request_type: 32u16,
1581        }
1582    }
1583    fn flags(&self) -> u16 {
1584        self.request.flags
1585    }
1586    fn payload(&self) -> &[u8] {
1587        self.request.buf()
1588    }
1589    type ReplyType<'buf> = (FibRuleHdr, IterableFibRuleAttrs<'buf>);
1590    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1591        Self::decode_request(buf)
1592    }
1593    fn lookup(
1594        buf: &[u8],
1595        offset: usize,
1596        missing_type: Option<u16>,
1597    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1598        Self::decode_request(buf)
1599            .1
1600            .lookup_attr(offset, missing_type)
1601    }
1602}
1603#[doc = "Remove an existing FIB rule\nRequest attributes:\n- [.push_iifname()](PushFibRuleAttrs::push_iifname)\n- [.push_goto()](PushFibRuleAttrs::push_goto)\n- [.push_priority()](PushFibRuleAttrs::push_priority)\n- [.push_fwmark()](PushFibRuleAttrs::push_fwmark)\n- [.push_flow()](PushFibRuleAttrs::push_flow)\n- [.push_tun_id()](PushFibRuleAttrs::push_tun_id)\n- [.push_suppress_ifgroup()](PushFibRuleAttrs::push_suppress_ifgroup)\n- [.push_suppress_prefixlen()](PushFibRuleAttrs::push_suppress_prefixlen)\n- [.push_table()](PushFibRuleAttrs::push_table)\n- [.push_fwmask()](PushFibRuleAttrs::push_fwmask)\n- [.push_oifname()](PushFibRuleAttrs::push_oifname)\n- [.push_l3mdev()](PushFibRuleAttrs::push_l3mdev)\n- [.push_uid_range()](PushFibRuleAttrs::push_uid_range)\n- [.push_protocol()](PushFibRuleAttrs::push_protocol)\n- [.push_ip_proto()](PushFibRuleAttrs::push_ip_proto)\n- [.push_sport_range()](PushFibRuleAttrs::push_sport_range)\n- [.push_dport_range()](PushFibRuleAttrs::push_dport_range)\n- [.push_dscp()](PushFibRuleAttrs::push_dscp)\n- [.push_flowlabel()](PushFibRuleAttrs::push_flowlabel)\n- [.push_flowlabel_mask()](PushFibRuleAttrs::push_flowlabel_mask)\n- [.push_sport_mask()](PushFibRuleAttrs::push_sport_mask)\n- [.push_dport_mask()](PushFibRuleAttrs::push_dport_mask)\n- [.push_dscp_mask()](PushFibRuleAttrs::push_dscp_mask)\n"]
1604#[derive(Debug)]
1605pub struct OpDelruleDo<'r> {
1606    request: Request<'r>,
1607}
1608impl<'r> OpDelruleDo<'r> {
1609    pub fn new(mut request: Request<'r>, header: &FibRuleHdr) -> Self {
1610        Self::write_header(request.buf_mut(), header);
1611        Self { request: request }
1612    }
1613    pub fn encode_request<'buf>(
1614        buf: &'buf mut Vec<u8>,
1615        header: &FibRuleHdr,
1616    ) -> PushFibRuleAttrs<&'buf mut Vec<u8>> {
1617        Self::write_header(buf, header);
1618        PushFibRuleAttrs::new(buf)
1619    }
1620    pub fn encode(&mut self) -> PushFibRuleAttrs<&mut Vec<u8>> {
1621        PushFibRuleAttrs::new(self.request.buf_mut())
1622    }
1623    pub fn into_encoder(self) -> PushFibRuleAttrs<RequestBuf<'r>> {
1624        PushFibRuleAttrs::new(self.request.buf)
1625    }
1626    pub fn decode_request<'a>(buf: &'a [u8]) -> (FibRuleHdr, IterableFibRuleAttrs<'a>) {
1627        let (header, attrs) = buf.split_at(buf.len().min(FibRuleHdr::len()));
1628        (
1629            FibRuleHdr::new_from_slice(header).unwrap_or_default(),
1630            IterableFibRuleAttrs::with_loc(attrs, buf.as_ptr() as usize),
1631        )
1632    }
1633    fn write_header<Prev: Rec>(prev: &mut Prev, header: &FibRuleHdr) {
1634        prev.as_rec_mut().extend(header.as_slice());
1635    }
1636}
1637impl NetlinkRequest for OpDelruleDo<'_> {
1638    fn protocol(&self) -> Protocol {
1639        Protocol::Raw {
1640            protonum: 0u16,
1641            request_type: 33u16,
1642        }
1643    }
1644    fn flags(&self) -> u16 {
1645        self.request.flags
1646    }
1647    fn payload(&self) -> &[u8] {
1648        self.request.buf()
1649    }
1650    type ReplyType<'buf> = (FibRuleHdr, IterableFibRuleAttrs<'buf>);
1651    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1652        Self::decode_request(buf)
1653    }
1654    fn lookup(
1655        buf: &[u8],
1656        offset: usize,
1657        missing_type: Option<u16>,
1658    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1659        Self::decode_request(buf)
1660            .1
1661            .lookup_attr(offset, missing_type)
1662    }
1663}
1664#[doc = "Dump all FIB rules\n\nReply attributes:\n- [.get_iifname()](IterableFibRuleAttrs::get_iifname)\n- [.get_goto()](IterableFibRuleAttrs::get_goto)\n- [.get_priority()](IterableFibRuleAttrs::get_priority)\n- [.get_fwmark()](IterableFibRuleAttrs::get_fwmark)\n- [.get_flow()](IterableFibRuleAttrs::get_flow)\n- [.get_tun_id()](IterableFibRuleAttrs::get_tun_id)\n- [.get_suppress_ifgroup()](IterableFibRuleAttrs::get_suppress_ifgroup)\n- [.get_suppress_prefixlen()](IterableFibRuleAttrs::get_suppress_prefixlen)\n- [.get_table()](IterableFibRuleAttrs::get_table)\n- [.get_fwmask()](IterableFibRuleAttrs::get_fwmask)\n- [.get_oifname()](IterableFibRuleAttrs::get_oifname)\n- [.get_l3mdev()](IterableFibRuleAttrs::get_l3mdev)\n- [.get_uid_range()](IterableFibRuleAttrs::get_uid_range)\n- [.get_protocol()](IterableFibRuleAttrs::get_protocol)\n- [.get_ip_proto()](IterableFibRuleAttrs::get_ip_proto)\n- [.get_sport_range()](IterableFibRuleAttrs::get_sport_range)\n- [.get_dport_range()](IterableFibRuleAttrs::get_dport_range)\n- [.get_dscp()](IterableFibRuleAttrs::get_dscp)\n- [.get_flowlabel()](IterableFibRuleAttrs::get_flowlabel)\n- [.get_flowlabel_mask()](IterableFibRuleAttrs::get_flowlabel_mask)\n- [.get_sport_mask()](IterableFibRuleAttrs::get_sport_mask)\n- [.get_dport_mask()](IterableFibRuleAttrs::get_dport_mask)\n- [.get_dscp_mask()](IterableFibRuleAttrs::get_dscp_mask)\n"]
1665#[derive(Debug)]
1666pub struct OpGetruleDump<'r> {
1667    request: Request<'r>,
1668}
1669impl<'r> OpGetruleDump<'r> {
1670    pub fn new(mut request: Request<'r>, header: &FibRuleHdr) -> Self {
1671        Self::write_header(request.buf_mut(), header);
1672        Self {
1673            request: request.set_dump(),
1674        }
1675    }
1676    pub fn encode_request<'buf>(
1677        buf: &'buf mut Vec<u8>,
1678        header: &FibRuleHdr,
1679    ) -> PushFibRuleAttrs<&'buf mut Vec<u8>> {
1680        Self::write_header(buf, header);
1681        PushFibRuleAttrs::new(buf)
1682    }
1683    pub fn encode(&mut self) -> PushFibRuleAttrs<&mut Vec<u8>> {
1684        PushFibRuleAttrs::new(self.request.buf_mut())
1685    }
1686    pub fn into_encoder(self) -> PushFibRuleAttrs<RequestBuf<'r>> {
1687        PushFibRuleAttrs::new(self.request.buf)
1688    }
1689    pub fn decode_request<'a>(buf: &'a [u8]) -> (FibRuleHdr, IterableFibRuleAttrs<'a>) {
1690        let (header, attrs) = buf.split_at(buf.len().min(FibRuleHdr::len()));
1691        (
1692            FibRuleHdr::new_from_slice(header).unwrap_or_default(),
1693            IterableFibRuleAttrs::with_loc(attrs, buf.as_ptr() as usize),
1694        )
1695    }
1696    fn write_header<Prev: Rec>(prev: &mut Prev, header: &FibRuleHdr) {
1697        prev.as_rec_mut().extend(header.as_slice());
1698    }
1699}
1700impl NetlinkRequest for OpGetruleDump<'_> {
1701    fn protocol(&self) -> Protocol {
1702        Protocol::Raw {
1703            protonum: 0u16,
1704            request_type: 34u16,
1705        }
1706    }
1707    fn flags(&self) -> u16 {
1708        self.request.flags
1709    }
1710    fn payload(&self) -> &[u8] {
1711        self.request.buf()
1712    }
1713    type ReplyType<'buf> = (FibRuleHdr, IterableFibRuleAttrs<'buf>);
1714    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1715        Self::decode_request(buf)
1716    }
1717    fn lookup(
1718        buf: &[u8],
1719        offset: usize,
1720        missing_type: Option<u16>,
1721    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1722        Self::decode_request(buf)
1723            .1
1724            .lookup_attr(offset, missing_type)
1725    }
1726}
1727#[derive(Debug)]
1728pub struct ChainedFinal<'a> {
1729    inner: Chained<'a>,
1730}
1731#[derive(Debug)]
1732pub struct Chained<'a> {
1733    buf: RequestBuf<'a>,
1734    first_seq: u32,
1735    lookups: Vec<(&'static str, LookupFn)>,
1736    last_header_offset: usize,
1737    last_kind: Option<RequestInfo>,
1738}
1739impl<'a> ChainedFinal<'a> {
1740    pub fn into_chained(self) -> Chained<'a> {
1741        self.inner
1742    }
1743    pub fn buf(&self) -> &Vec<u8> {
1744        self.inner.buf()
1745    }
1746    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1747        self.inner.buf_mut()
1748    }
1749    fn get_index(&self, seq: u32) -> Option<u32> {
1750        let min = self.inner.first_seq;
1751        let max = min.wrapping_add(self.inner.lookups.len() as u32);
1752        return if min <= max {
1753            (min..max).contains(&seq).then(|| seq - min)
1754        } else if min <= seq {
1755            Some(seq - min)
1756        } else if seq < max {
1757            Some(u32::MAX - min + seq)
1758        } else {
1759            None
1760        };
1761    }
1762}
1763impl crate::traits::NetlinkChained for ChainedFinal<'_> {
1764    fn protonum(&self) -> u16 {
1765        PROTONUM
1766    }
1767    fn payload(&self) -> &[u8] {
1768        self.buf()
1769    }
1770    fn chain_len(&self) -> usize {
1771        self.inner.lookups.len()
1772    }
1773    fn get_index(&self, seq: u32) -> Option<usize> {
1774        self.get_index(seq).map(|n| n as usize)
1775    }
1776    fn name(&self, index: usize) -> &'static str {
1777        self.inner.lookups[index].0
1778    }
1779    fn lookup(&self, index: usize) -> LookupFn {
1780        self.inner.lookups[index].1
1781    }
1782}
1783impl Chained<'static> {
1784    pub fn new(first_seq: u32) -> Self {
1785        Self::new_from_buf(Vec::new(), first_seq)
1786    }
1787    pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
1788        Self {
1789            buf: RequestBuf::Own(buf),
1790            first_seq,
1791            lookups: Vec::new(),
1792            last_header_offset: 0,
1793            last_kind: None,
1794        }
1795    }
1796    pub fn into_buf(self) -> Vec<u8> {
1797        match self.buf {
1798            RequestBuf::Own(buf) => buf,
1799            _ => unreachable!(),
1800        }
1801    }
1802}
1803impl<'a> Chained<'a> {
1804    pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
1805        Self {
1806            buf: RequestBuf::Ref(buf),
1807            first_seq,
1808            lookups: Vec::new(),
1809            last_header_offset: 0,
1810            last_kind: None,
1811        }
1812    }
1813    pub fn finalize(mut self) -> ChainedFinal<'a> {
1814        self.update_header();
1815        ChainedFinal { inner: self }
1816    }
1817    pub fn request(&mut self) -> Request<'_> {
1818        self.update_header();
1819        self.last_header_offset = self.buf().len();
1820        self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
1821        let mut request = Request::new_extend(self.buf.buf_mut());
1822        self.last_kind = None;
1823        request.writeback = Some(&mut self.last_kind);
1824        request
1825    }
1826    pub fn buf(&self) -> &Vec<u8> {
1827        self.buf.buf()
1828    }
1829    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1830        self.buf.buf_mut()
1831    }
1832    fn update_header(&mut self) {
1833        let Some(RequestInfo {
1834            protocol,
1835            flags,
1836            name,
1837            lookup,
1838        }) = self.last_kind
1839        else {
1840            if !self.buf().is_empty() {
1841                assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
1842                self.buf.buf_mut().truncate(self.last_header_offset);
1843            }
1844            return;
1845        };
1846        let header_offset = self.last_header_offset;
1847        let request_type = match protocol {
1848            Protocol::Raw { request_type, .. } => request_type,
1849            Protocol::Generic(_) => unreachable!(),
1850        };
1851        let index = self.lookups.len();
1852        let seq = self.first_seq.wrapping_add(index as u32);
1853        self.lookups.push((name, lookup));
1854        let buf = self.buf_mut();
1855        align(buf);
1856        let header = Nlmsghdr {
1857            len: (buf.len() - header_offset) as u32,
1858            r#type: request_type,
1859            flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
1860            seq,
1861            pid: 0,
1862        };
1863        buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
1864    }
1865}
1866use crate::traits::LookupFn;
1867use crate::utils::RequestBuf;
1868#[derive(Debug)]
1869pub struct Request<'buf> {
1870    buf: RequestBuf<'buf>,
1871    flags: u16,
1872    writeback: Option<&'buf mut Option<RequestInfo>>,
1873}
1874#[allow(unused)]
1875#[derive(Debug, Clone)]
1876pub struct RequestInfo {
1877    protocol: Protocol,
1878    flags: u16,
1879    name: &'static str,
1880    lookup: LookupFn,
1881}
1882impl Request<'static> {
1883    pub fn new() -> Self {
1884        Self::new_from_buf(Vec::new())
1885    }
1886    pub fn new_from_buf(buf: Vec<u8>) -> Self {
1887        Self {
1888            flags: 0,
1889            buf: RequestBuf::Own(buf),
1890            writeback: None,
1891        }
1892    }
1893    pub fn into_buf(self) -> Vec<u8> {
1894        match self.buf {
1895            RequestBuf::Own(buf) => buf,
1896            _ => unreachable!(),
1897        }
1898    }
1899}
1900impl<'buf> Request<'buf> {
1901    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1902        buf.clear();
1903        Self::new_extend(buf)
1904    }
1905    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1906        Self {
1907            flags: 0,
1908            buf: RequestBuf::Ref(buf),
1909            writeback: None,
1910        }
1911    }
1912    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1913        let Some(writeback) = &mut self.writeback else {
1914            return;
1915        };
1916        **writeback = Some(RequestInfo {
1917            protocol,
1918            flags: self.flags,
1919            name,
1920            lookup,
1921        })
1922    }
1923    pub fn buf(&self) -> &Vec<u8> {
1924        self.buf.buf()
1925    }
1926    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1927        self.buf.buf_mut()
1928    }
1929    #[doc = "Set `NLM_F_CREATE` flag"]
1930    pub fn set_create(mut self) -> Self {
1931        self.flags |= consts::NLM_F_CREATE as u16;
1932        self
1933    }
1934    #[doc = "Set `NLM_F_EXCL` flag"]
1935    pub fn set_excl(mut self) -> Self {
1936        self.flags |= consts::NLM_F_EXCL as u16;
1937        self
1938    }
1939    #[doc = "Set `NLM_F_REPLACE` flag"]
1940    pub fn set_replace(mut self) -> Self {
1941        self.flags |= consts::NLM_F_REPLACE as u16;
1942        self
1943    }
1944    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1945    pub fn set_change(self) -> Self {
1946        self.set_create().set_replace()
1947    }
1948    #[doc = "Set `NLM_F_APPEND` flag"]
1949    pub fn set_append(mut self) -> Self {
1950        self.flags |= consts::NLM_F_APPEND as u16;
1951        self
1952    }
1953    #[doc = "Set `self.flags |= flags`"]
1954    pub fn set_flags(mut self, flags: u16) -> Self {
1955        self.flags |= flags;
1956        self
1957    }
1958    #[doc = "Set `self.flags ^= self.flags & flags`"]
1959    pub fn unset_flags(mut self, flags: u16) -> Self {
1960        self.flags ^= self.flags & flags;
1961        self
1962    }
1963    #[doc = "Set `NLM_F_DUMP` flag"]
1964    fn set_dump(mut self) -> Self {
1965        self.flags |= consts::NLM_F_DUMP as u16;
1966        self
1967    }
1968    #[doc = "Add new FIB rule\nRequest attributes:\n- [.push_iifname()](PushFibRuleAttrs::push_iifname)\n- [.push_goto()](PushFibRuleAttrs::push_goto)\n- [.push_priority()](PushFibRuleAttrs::push_priority)\n- [.push_fwmark()](PushFibRuleAttrs::push_fwmark)\n- [.push_flow()](PushFibRuleAttrs::push_flow)\n- [.push_tun_id()](PushFibRuleAttrs::push_tun_id)\n- [.push_suppress_ifgroup()](PushFibRuleAttrs::push_suppress_ifgroup)\n- [.push_suppress_prefixlen()](PushFibRuleAttrs::push_suppress_prefixlen)\n- [.push_table()](PushFibRuleAttrs::push_table)\n- [.push_fwmask()](PushFibRuleAttrs::push_fwmask)\n- [.push_oifname()](PushFibRuleAttrs::push_oifname)\n- [.push_l3mdev()](PushFibRuleAttrs::push_l3mdev)\n- [.push_uid_range()](PushFibRuleAttrs::push_uid_range)\n- [.push_protocol()](PushFibRuleAttrs::push_protocol)\n- [.push_ip_proto()](PushFibRuleAttrs::push_ip_proto)\n- [.push_sport_range()](PushFibRuleAttrs::push_sport_range)\n- [.push_dport_range()](PushFibRuleAttrs::push_dport_range)\n- [.push_dscp()](PushFibRuleAttrs::push_dscp)\n- [.push_flowlabel()](PushFibRuleAttrs::push_flowlabel)\n- [.push_flowlabel_mask()](PushFibRuleAttrs::push_flowlabel_mask)\n- [.push_sport_mask()](PushFibRuleAttrs::push_sport_mask)\n- [.push_dport_mask()](PushFibRuleAttrs::push_dport_mask)\n- [.push_dscp_mask()](PushFibRuleAttrs::push_dscp_mask)\n"]
1969    pub fn op_newrule_do(self, header: &FibRuleHdr) -> OpNewruleDo<'buf> {
1970        let mut res = OpNewruleDo::new(self, header);
1971        res.request
1972            .do_writeback(res.protocol(), "op-newrule-do", OpNewruleDo::lookup);
1973        res
1974    }
1975    #[doc = "Remove an existing FIB rule\nRequest attributes:\n- [.push_iifname()](PushFibRuleAttrs::push_iifname)\n- [.push_goto()](PushFibRuleAttrs::push_goto)\n- [.push_priority()](PushFibRuleAttrs::push_priority)\n- [.push_fwmark()](PushFibRuleAttrs::push_fwmark)\n- [.push_flow()](PushFibRuleAttrs::push_flow)\n- [.push_tun_id()](PushFibRuleAttrs::push_tun_id)\n- [.push_suppress_ifgroup()](PushFibRuleAttrs::push_suppress_ifgroup)\n- [.push_suppress_prefixlen()](PushFibRuleAttrs::push_suppress_prefixlen)\n- [.push_table()](PushFibRuleAttrs::push_table)\n- [.push_fwmask()](PushFibRuleAttrs::push_fwmask)\n- [.push_oifname()](PushFibRuleAttrs::push_oifname)\n- [.push_l3mdev()](PushFibRuleAttrs::push_l3mdev)\n- [.push_uid_range()](PushFibRuleAttrs::push_uid_range)\n- [.push_protocol()](PushFibRuleAttrs::push_protocol)\n- [.push_ip_proto()](PushFibRuleAttrs::push_ip_proto)\n- [.push_sport_range()](PushFibRuleAttrs::push_sport_range)\n- [.push_dport_range()](PushFibRuleAttrs::push_dport_range)\n- [.push_dscp()](PushFibRuleAttrs::push_dscp)\n- [.push_flowlabel()](PushFibRuleAttrs::push_flowlabel)\n- [.push_flowlabel_mask()](PushFibRuleAttrs::push_flowlabel_mask)\n- [.push_sport_mask()](PushFibRuleAttrs::push_sport_mask)\n- [.push_dport_mask()](PushFibRuleAttrs::push_dport_mask)\n- [.push_dscp_mask()](PushFibRuleAttrs::push_dscp_mask)\n"]
1976    pub fn op_delrule_do(self, header: &FibRuleHdr) -> OpDelruleDo<'buf> {
1977        let mut res = OpDelruleDo::new(self, header);
1978        res.request
1979            .do_writeback(res.protocol(), "op-delrule-do", OpDelruleDo::lookup);
1980        res
1981    }
1982    #[doc = "Dump all FIB rules\n\nReply attributes:\n- [.get_iifname()](IterableFibRuleAttrs::get_iifname)\n- [.get_goto()](IterableFibRuleAttrs::get_goto)\n- [.get_priority()](IterableFibRuleAttrs::get_priority)\n- [.get_fwmark()](IterableFibRuleAttrs::get_fwmark)\n- [.get_flow()](IterableFibRuleAttrs::get_flow)\n- [.get_tun_id()](IterableFibRuleAttrs::get_tun_id)\n- [.get_suppress_ifgroup()](IterableFibRuleAttrs::get_suppress_ifgroup)\n- [.get_suppress_prefixlen()](IterableFibRuleAttrs::get_suppress_prefixlen)\n- [.get_table()](IterableFibRuleAttrs::get_table)\n- [.get_fwmask()](IterableFibRuleAttrs::get_fwmask)\n- [.get_oifname()](IterableFibRuleAttrs::get_oifname)\n- [.get_l3mdev()](IterableFibRuleAttrs::get_l3mdev)\n- [.get_uid_range()](IterableFibRuleAttrs::get_uid_range)\n- [.get_protocol()](IterableFibRuleAttrs::get_protocol)\n- [.get_ip_proto()](IterableFibRuleAttrs::get_ip_proto)\n- [.get_sport_range()](IterableFibRuleAttrs::get_sport_range)\n- [.get_dport_range()](IterableFibRuleAttrs::get_dport_range)\n- [.get_dscp()](IterableFibRuleAttrs::get_dscp)\n- [.get_flowlabel()](IterableFibRuleAttrs::get_flowlabel)\n- [.get_flowlabel_mask()](IterableFibRuleAttrs::get_flowlabel_mask)\n- [.get_sport_mask()](IterableFibRuleAttrs::get_sport_mask)\n- [.get_dport_mask()](IterableFibRuleAttrs::get_dport_mask)\n- [.get_dscp_mask()](IterableFibRuleAttrs::get_dscp_mask)\n"]
1983    pub fn op_getrule_dump(self, header: &FibRuleHdr) -> OpGetruleDump<'buf> {
1984        let mut res = OpGetruleDump::new(self, header);
1985        res.request
1986            .do_writeback(res.protocol(), "op-getrule-dump", OpGetruleDump::lookup);
1987        res
1988    }
1989}
1990#[cfg(test)]
1991mod generated_tests {
1992    use super::*;
1993    #[test]
1994    fn tests() {
1995        let _ = IterableFibRuleAttrs::get_dport_mask;
1996        let _ = IterableFibRuleAttrs::get_dport_range;
1997        let _ = IterableFibRuleAttrs::get_dscp;
1998        let _ = IterableFibRuleAttrs::get_dscp_mask;
1999        let _ = IterableFibRuleAttrs::get_flow;
2000        let _ = IterableFibRuleAttrs::get_flowlabel;
2001        let _ = IterableFibRuleAttrs::get_flowlabel_mask;
2002        let _ = IterableFibRuleAttrs::get_fwmark;
2003        let _ = IterableFibRuleAttrs::get_fwmask;
2004        let _ = IterableFibRuleAttrs::get_goto;
2005        let _ = IterableFibRuleAttrs::get_iifname;
2006        let _ = IterableFibRuleAttrs::get_ip_proto;
2007        let _ = IterableFibRuleAttrs::get_l3mdev;
2008        let _ = IterableFibRuleAttrs::get_oifname;
2009        let _ = IterableFibRuleAttrs::get_priority;
2010        let _ = IterableFibRuleAttrs::get_protocol;
2011        let _ = IterableFibRuleAttrs::get_sport_mask;
2012        let _ = IterableFibRuleAttrs::get_sport_range;
2013        let _ = IterableFibRuleAttrs::get_suppress_ifgroup;
2014        let _ = IterableFibRuleAttrs::get_suppress_prefixlen;
2015        let _ = IterableFibRuleAttrs::get_table;
2016        let _ = IterableFibRuleAttrs::get_tun_id;
2017        let _ = IterableFibRuleAttrs::get_uid_range;
2018        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_dport_mask;
2019        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_dport_range;
2020        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_dscp;
2021        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_dscp_mask;
2022        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_flow;
2023        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_flowlabel;
2024        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_flowlabel_mask;
2025        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_fwmark;
2026        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_fwmask;
2027        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_goto;
2028        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_iifname;
2029        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_ip_proto;
2030        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_l3mdev;
2031        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_oifname;
2032        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_priority;
2033        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_protocol;
2034        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_sport_mask;
2035        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_sport_range;
2036        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_suppress_ifgroup;
2037        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_suppress_prefixlen;
2038        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_table;
2039        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_tun_id;
2040        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_uid_range;
2041    }
2042}