Skip to main content

netlink_bindings/rt-rule/
mod.rs

1#![doc = "FIB rule management over rtnetlink.\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 mut pos;
890        let mut r#type;
891        loop {
892            pos = self.pos;
893            r#type = None;
894            if self.buf.len() == self.pos {
895                return None;
896            }
897            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
898                self.pos = self.buf.len();
899                break;
900            };
901            r#type = Some(header.r#type);
902            let res = match header.r#type {
903                1u16 => FibRuleAttrs::Dst({
904                    let res = parse_ip(next);
905                    let Some(val) = res else { break };
906                    val
907                }),
908                2u16 => FibRuleAttrs::Src({
909                    let res = parse_ip(next);
910                    let Some(val) = res else { break };
911                    val
912                }),
913                3u16 => FibRuleAttrs::Iifname({
914                    let res = CStr::from_bytes_with_nul(next).ok();
915                    let Some(val) = res else { break };
916                    val
917                }),
918                4u16 => FibRuleAttrs::Goto({
919                    let res = parse_u32(next);
920                    let Some(val) = res else { break };
921                    val
922                }),
923                5u16 => FibRuleAttrs::Unused2({
924                    let res = Some(next);
925                    let Some(val) = res else { break };
926                    val
927                }),
928                6u16 => FibRuleAttrs::Priority({
929                    let res = parse_u32(next);
930                    let Some(val) = res else { break };
931                    val
932                }),
933                7u16 => FibRuleAttrs::Unused3({
934                    let res = Some(next);
935                    let Some(val) = res else { break };
936                    val
937                }),
938                8u16 => FibRuleAttrs::Unused4({
939                    let res = Some(next);
940                    let Some(val) = res else { break };
941                    val
942                }),
943                9u16 => FibRuleAttrs::Unused5({
944                    let res = Some(next);
945                    let Some(val) = res else { break };
946                    val
947                }),
948                10u16 => FibRuleAttrs::Fwmark({
949                    let res = parse_u32(next);
950                    let Some(val) = res else { break };
951                    val
952                }),
953                11u16 => FibRuleAttrs::Flow({
954                    let res = parse_u32(next);
955                    let Some(val) = res else { break };
956                    val
957                }),
958                12u16 => FibRuleAttrs::TunId({
959                    let res = parse_u64(next);
960                    let Some(val) = res else { break };
961                    val
962                }),
963                13u16 => FibRuleAttrs::SuppressIfgroup({
964                    let res = parse_u32(next);
965                    let Some(val) = res else { break };
966                    val
967                }),
968                14u16 => FibRuleAttrs::SuppressPrefixlen({
969                    let res = parse_u32(next);
970                    let Some(val) = res else { break };
971                    val
972                }),
973                15u16 => FibRuleAttrs::Table({
974                    let res = parse_u32(next);
975                    let Some(val) = res else { break };
976                    val
977                }),
978                16u16 => FibRuleAttrs::Fwmask({
979                    let res = parse_u32(next);
980                    let Some(val) = res else { break };
981                    val
982                }),
983                17u16 => FibRuleAttrs::Oifname({
984                    let res = CStr::from_bytes_with_nul(next).ok();
985                    let Some(val) = res else { break };
986                    val
987                }),
988                18u16 => FibRuleAttrs::Pad({
989                    let res = Some(next);
990                    let Some(val) = res else { break };
991                    val
992                }),
993                19u16 => FibRuleAttrs::L3mdev({
994                    let res = parse_u8(next);
995                    let Some(val) = res else { break };
996                    val
997                }),
998                20u16 => FibRuleAttrs::UidRange({
999                    let res = Some(FibRuleUidRange::new_from_zeroed(next));
1000                    let Some(val) = res else { break };
1001                    val
1002                }),
1003                21u16 => FibRuleAttrs::Protocol({
1004                    let res = parse_u8(next);
1005                    let Some(val) = res else { break };
1006                    val
1007                }),
1008                22u16 => FibRuleAttrs::IpProto({
1009                    let res = parse_u8(next);
1010                    let Some(val) = res else { break };
1011                    val
1012                }),
1013                23u16 => FibRuleAttrs::SportRange({
1014                    let res = Some(FibRulePortRange::new_from_zeroed(next));
1015                    let Some(val) = res else { break };
1016                    val
1017                }),
1018                24u16 => FibRuleAttrs::DportRange({
1019                    let res = Some(FibRulePortRange::new_from_zeroed(next));
1020                    let Some(val) = res else { break };
1021                    val
1022                }),
1023                25u16 => FibRuleAttrs::Dscp({
1024                    let res = parse_u8(next);
1025                    let Some(val) = res else { break };
1026                    val
1027                }),
1028                26u16 => FibRuleAttrs::Flowlabel({
1029                    let res = parse_be_u32(next);
1030                    let Some(val) = res else { break };
1031                    val
1032                }),
1033                27u16 => FibRuleAttrs::FlowlabelMask({
1034                    let res = parse_be_u32(next);
1035                    let Some(val) = res else { break };
1036                    val
1037                }),
1038                28u16 => FibRuleAttrs::SportMask({
1039                    let res = parse_u16(next);
1040                    let Some(val) = res else { break };
1041                    val
1042                }),
1043                29u16 => FibRuleAttrs::DportMask({
1044                    let res = parse_u16(next);
1045                    let Some(val) = res else { break };
1046                    val
1047                }),
1048                30u16 => FibRuleAttrs::DscpMask({
1049                    let res = parse_u8(next);
1050                    let Some(val) = res else { break };
1051                    val
1052                }),
1053                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1054                n => continue,
1055            };
1056            return Some(Ok(res));
1057        }
1058        Some(Err(ErrorContext::new(
1059            "FibRuleAttrs",
1060            r#type.and_then(|t| FibRuleAttrs::attr_from_type(t)),
1061            self.orig_loc,
1062            self.buf.as_ptr().wrapping_add(pos) as usize,
1063        )))
1064    }
1065}
1066impl<'a> std::fmt::Debug for IterableFibRuleAttrs<'_> {
1067    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1068        let mut fmt = f.debug_struct("FibRuleAttrs");
1069        for attr in self.clone() {
1070            let attr = match attr {
1071                Ok(a) => a,
1072                Err(err) => {
1073                    fmt.finish()?;
1074                    f.write_str("Err(")?;
1075                    err.fmt(f)?;
1076                    return f.write_str(")");
1077                }
1078            };
1079            match attr {
1080                FibRuleAttrs::Dst(val) => fmt.field("Dst", &val),
1081                FibRuleAttrs::Src(val) => fmt.field("Src", &val),
1082                FibRuleAttrs::Iifname(val) => fmt.field("Iifname", &val),
1083                FibRuleAttrs::Goto(val) => fmt.field("Goto", &val),
1084                FibRuleAttrs::Unused2(val) => fmt.field("Unused2", &val),
1085                FibRuleAttrs::Priority(val) => fmt.field("Priority", &val),
1086                FibRuleAttrs::Unused3(val) => fmt.field("Unused3", &val),
1087                FibRuleAttrs::Unused4(val) => fmt.field("Unused4", &val),
1088                FibRuleAttrs::Unused5(val) => fmt.field("Unused5", &val),
1089                FibRuleAttrs::Fwmark(val) => fmt.field("Fwmark", &val),
1090                FibRuleAttrs::Flow(val) => fmt.field("Flow", &val),
1091                FibRuleAttrs::TunId(val) => fmt.field("TunId", &val),
1092                FibRuleAttrs::SuppressIfgroup(val) => fmt.field("SuppressIfgroup", &val),
1093                FibRuleAttrs::SuppressPrefixlen(val) => fmt.field("SuppressPrefixlen", &val),
1094                FibRuleAttrs::Table(val) => fmt.field("Table", &val),
1095                FibRuleAttrs::Fwmask(val) => fmt.field("Fwmask", &val),
1096                FibRuleAttrs::Oifname(val) => fmt.field("Oifname", &val),
1097                FibRuleAttrs::Pad(val) => fmt.field("Pad", &val),
1098                FibRuleAttrs::L3mdev(val) => fmt.field("L3mdev", &val),
1099                FibRuleAttrs::UidRange(val) => fmt.field("UidRange", &val),
1100                FibRuleAttrs::Protocol(val) => fmt.field("Protocol", &val),
1101                FibRuleAttrs::IpProto(val) => fmt.field("IpProto", &val),
1102                FibRuleAttrs::SportRange(val) => fmt.field("SportRange", &val),
1103                FibRuleAttrs::DportRange(val) => fmt.field("DportRange", &val),
1104                FibRuleAttrs::Dscp(val) => fmt.field("Dscp", &val),
1105                FibRuleAttrs::Flowlabel(val) => fmt.field("Flowlabel", &val),
1106                FibRuleAttrs::FlowlabelMask(val) => fmt.field("FlowlabelMask", &val),
1107                FibRuleAttrs::SportMask(val) => fmt.field("SportMask", &val),
1108                FibRuleAttrs::DportMask(val) => fmt.field("DportMask", &val),
1109                FibRuleAttrs::DscpMask(val) => fmt.field("DscpMask", &val),
1110            };
1111        }
1112        fmt.finish()
1113    }
1114}
1115impl IterableFibRuleAttrs<'_> {
1116    pub fn lookup_attr(
1117        &self,
1118        offset: usize,
1119        missing_type: Option<u16>,
1120    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1121        let mut stack = Vec::new();
1122        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1123        if missing_type.is_some() && cur == offset {
1124            stack.push(("FibRuleAttrs", offset));
1125            return (
1126                stack,
1127                missing_type.and_then(|t| FibRuleAttrs::attr_from_type(t)),
1128            );
1129        }
1130        if cur > offset || cur + self.buf.len() < offset {
1131            return (stack, None);
1132        }
1133        let mut attrs = self.clone();
1134        let mut last_off = cur + attrs.pos;
1135        while let Some(attr) = attrs.next() {
1136            let Ok(attr) = attr else { break };
1137            match attr {
1138                FibRuleAttrs::Dst(val) => {
1139                    if last_off == offset {
1140                        stack.push(("Dst", last_off));
1141                        break;
1142                    }
1143                }
1144                FibRuleAttrs::Src(val) => {
1145                    if last_off == offset {
1146                        stack.push(("Src", last_off));
1147                        break;
1148                    }
1149                }
1150                FibRuleAttrs::Iifname(val) => {
1151                    if last_off == offset {
1152                        stack.push(("Iifname", last_off));
1153                        break;
1154                    }
1155                }
1156                FibRuleAttrs::Goto(val) => {
1157                    if last_off == offset {
1158                        stack.push(("Goto", last_off));
1159                        break;
1160                    }
1161                }
1162                FibRuleAttrs::Unused2(val) => {
1163                    if last_off == offset {
1164                        stack.push(("Unused2", last_off));
1165                        break;
1166                    }
1167                }
1168                FibRuleAttrs::Priority(val) => {
1169                    if last_off == offset {
1170                        stack.push(("Priority", last_off));
1171                        break;
1172                    }
1173                }
1174                FibRuleAttrs::Unused3(val) => {
1175                    if last_off == offset {
1176                        stack.push(("Unused3", last_off));
1177                        break;
1178                    }
1179                }
1180                FibRuleAttrs::Unused4(val) => {
1181                    if last_off == offset {
1182                        stack.push(("Unused4", last_off));
1183                        break;
1184                    }
1185                }
1186                FibRuleAttrs::Unused5(val) => {
1187                    if last_off == offset {
1188                        stack.push(("Unused5", last_off));
1189                        break;
1190                    }
1191                }
1192                FibRuleAttrs::Fwmark(val) => {
1193                    if last_off == offset {
1194                        stack.push(("Fwmark", last_off));
1195                        break;
1196                    }
1197                }
1198                FibRuleAttrs::Flow(val) => {
1199                    if last_off == offset {
1200                        stack.push(("Flow", last_off));
1201                        break;
1202                    }
1203                }
1204                FibRuleAttrs::TunId(val) => {
1205                    if last_off == offset {
1206                        stack.push(("TunId", last_off));
1207                        break;
1208                    }
1209                }
1210                FibRuleAttrs::SuppressIfgroup(val) => {
1211                    if last_off == offset {
1212                        stack.push(("SuppressIfgroup", last_off));
1213                        break;
1214                    }
1215                }
1216                FibRuleAttrs::SuppressPrefixlen(val) => {
1217                    if last_off == offset {
1218                        stack.push(("SuppressPrefixlen", last_off));
1219                        break;
1220                    }
1221                }
1222                FibRuleAttrs::Table(val) => {
1223                    if last_off == offset {
1224                        stack.push(("Table", last_off));
1225                        break;
1226                    }
1227                }
1228                FibRuleAttrs::Fwmask(val) => {
1229                    if last_off == offset {
1230                        stack.push(("Fwmask", last_off));
1231                        break;
1232                    }
1233                }
1234                FibRuleAttrs::Oifname(val) => {
1235                    if last_off == offset {
1236                        stack.push(("Oifname", last_off));
1237                        break;
1238                    }
1239                }
1240                FibRuleAttrs::Pad(val) => {
1241                    if last_off == offset {
1242                        stack.push(("Pad", last_off));
1243                        break;
1244                    }
1245                }
1246                FibRuleAttrs::L3mdev(val) => {
1247                    if last_off == offset {
1248                        stack.push(("L3mdev", last_off));
1249                        break;
1250                    }
1251                }
1252                FibRuleAttrs::UidRange(val) => {
1253                    if last_off == offset {
1254                        stack.push(("UidRange", last_off));
1255                        break;
1256                    }
1257                }
1258                FibRuleAttrs::Protocol(val) => {
1259                    if last_off == offset {
1260                        stack.push(("Protocol", last_off));
1261                        break;
1262                    }
1263                }
1264                FibRuleAttrs::IpProto(val) => {
1265                    if last_off == offset {
1266                        stack.push(("IpProto", last_off));
1267                        break;
1268                    }
1269                }
1270                FibRuleAttrs::SportRange(val) => {
1271                    if last_off == offset {
1272                        stack.push(("SportRange", last_off));
1273                        break;
1274                    }
1275                }
1276                FibRuleAttrs::DportRange(val) => {
1277                    if last_off == offset {
1278                        stack.push(("DportRange", last_off));
1279                        break;
1280                    }
1281                }
1282                FibRuleAttrs::Dscp(val) => {
1283                    if last_off == offset {
1284                        stack.push(("Dscp", last_off));
1285                        break;
1286                    }
1287                }
1288                FibRuleAttrs::Flowlabel(val) => {
1289                    if last_off == offset {
1290                        stack.push(("Flowlabel", last_off));
1291                        break;
1292                    }
1293                }
1294                FibRuleAttrs::FlowlabelMask(val) => {
1295                    if last_off == offset {
1296                        stack.push(("FlowlabelMask", last_off));
1297                        break;
1298                    }
1299                }
1300                FibRuleAttrs::SportMask(val) => {
1301                    if last_off == offset {
1302                        stack.push(("SportMask", last_off));
1303                        break;
1304                    }
1305                }
1306                FibRuleAttrs::DportMask(val) => {
1307                    if last_off == offset {
1308                        stack.push(("DportMask", last_off));
1309                        break;
1310                    }
1311                }
1312                FibRuleAttrs::DscpMask(val) => {
1313                    if last_off == offset {
1314                        stack.push(("DscpMask", last_off));
1315                        break;
1316                    }
1317                }
1318                _ => {}
1319            };
1320            last_off = cur + attrs.pos;
1321        }
1322        if !stack.is_empty() {
1323            stack.push(("FibRuleAttrs", cur));
1324        }
1325        (stack, None)
1326    }
1327}
1328pub struct PushFibRuleAttrs<Prev: Pusher> {
1329    pub(crate) prev: Option<Prev>,
1330    pub(crate) header_offset: Option<usize>,
1331}
1332impl<Prev: Pusher> Pusher for PushFibRuleAttrs<Prev> {
1333    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1334        self.prev.as_mut().unwrap().as_vec_mut()
1335    }
1336    fn as_vec(&self) -> &Vec<u8> {
1337        self.prev.as_ref().unwrap().as_vec()
1338    }
1339}
1340impl<Prev: Pusher> PushFibRuleAttrs<Prev> {
1341    pub fn new(prev: Prev) -> Self {
1342        Self {
1343            prev: Some(prev),
1344            header_offset: None,
1345        }
1346    }
1347    pub fn end_nested(mut self) -> Prev {
1348        let mut prev = self.prev.take().unwrap();
1349        if let Some(header_offset) = &self.header_offset {
1350            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1351        }
1352        prev
1353    }
1354    pub fn push_dst(mut self, value: std::net::IpAddr) -> Self {
1355        push_header(self.as_vec_mut(), 1u16, {
1356            match &value {
1357                IpAddr::V4(_) => 4,
1358                IpAddr::V6(_) => 16,
1359            }
1360        } as u16);
1361        encode_ip(self.as_vec_mut(), value);
1362        self
1363    }
1364    pub fn push_src(mut self, value: std::net::IpAddr) -> Self {
1365        push_header(self.as_vec_mut(), 2u16, {
1366            match &value {
1367                IpAddr::V4(_) => 4,
1368                IpAddr::V6(_) => 16,
1369            }
1370        } as u16);
1371        encode_ip(self.as_vec_mut(), value);
1372        self
1373    }
1374    pub fn push_iifname(mut self, value: &CStr) -> Self {
1375        push_header(
1376            self.as_vec_mut(),
1377            3u16,
1378            value.to_bytes_with_nul().len() as u16,
1379        );
1380        self.as_vec_mut().extend(value.to_bytes_with_nul());
1381        self
1382    }
1383    pub fn push_iifname_bytes(mut self, value: &[u8]) -> Self {
1384        push_header(self.as_vec_mut(), 3u16, (value.len() + 1) as u16);
1385        self.as_vec_mut().extend(value);
1386        self.as_vec_mut().push(0);
1387        self
1388    }
1389    pub fn push_goto(mut self, value: u32) -> Self {
1390        push_header(self.as_vec_mut(), 4u16, 4 as u16);
1391        self.as_vec_mut().extend(value.to_ne_bytes());
1392        self
1393    }
1394    pub fn push_unused2(mut self, value: &[u8]) -> Self {
1395        push_header(self.as_vec_mut(), 5u16, value.len() as u16);
1396        self.as_vec_mut().extend(value);
1397        self
1398    }
1399    pub fn push_priority(mut self, value: u32) -> Self {
1400        push_header(self.as_vec_mut(), 6u16, 4 as u16);
1401        self.as_vec_mut().extend(value.to_ne_bytes());
1402        self
1403    }
1404    pub fn push_unused3(mut self, value: &[u8]) -> Self {
1405        push_header(self.as_vec_mut(), 7u16, value.len() as u16);
1406        self.as_vec_mut().extend(value);
1407        self
1408    }
1409    pub fn push_unused4(mut self, value: &[u8]) -> Self {
1410        push_header(self.as_vec_mut(), 8u16, value.len() as u16);
1411        self.as_vec_mut().extend(value);
1412        self
1413    }
1414    pub fn push_unused5(mut self, value: &[u8]) -> Self {
1415        push_header(self.as_vec_mut(), 9u16, value.len() as u16);
1416        self.as_vec_mut().extend(value);
1417        self
1418    }
1419    pub fn push_fwmark(mut self, value: u32) -> Self {
1420        push_header(self.as_vec_mut(), 10u16, 4 as u16);
1421        self.as_vec_mut().extend(value.to_ne_bytes());
1422        self
1423    }
1424    pub fn push_flow(mut self, value: u32) -> Self {
1425        push_header(self.as_vec_mut(), 11u16, 4 as u16);
1426        self.as_vec_mut().extend(value.to_ne_bytes());
1427        self
1428    }
1429    pub fn push_tun_id(mut self, value: u64) -> Self {
1430        push_header(self.as_vec_mut(), 12u16, 8 as u16);
1431        self.as_vec_mut().extend(value.to_ne_bytes());
1432        self
1433    }
1434    pub fn push_suppress_ifgroup(mut self, value: u32) -> Self {
1435        push_header(self.as_vec_mut(), 13u16, 4 as u16);
1436        self.as_vec_mut().extend(value.to_ne_bytes());
1437        self
1438    }
1439    pub fn push_suppress_prefixlen(mut self, value: u32) -> Self {
1440        push_header(self.as_vec_mut(), 14u16, 4 as u16);
1441        self.as_vec_mut().extend(value.to_ne_bytes());
1442        self
1443    }
1444    pub fn push_table(mut self, value: u32) -> Self {
1445        push_header(self.as_vec_mut(), 15u16, 4 as u16);
1446        self.as_vec_mut().extend(value.to_ne_bytes());
1447        self
1448    }
1449    pub fn push_fwmask(mut self, value: u32) -> Self {
1450        push_header(self.as_vec_mut(), 16u16, 4 as u16);
1451        self.as_vec_mut().extend(value.to_ne_bytes());
1452        self
1453    }
1454    pub fn push_oifname(mut self, value: &CStr) -> Self {
1455        push_header(
1456            self.as_vec_mut(),
1457            17u16,
1458            value.to_bytes_with_nul().len() as u16,
1459        );
1460        self.as_vec_mut().extend(value.to_bytes_with_nul());
1461        self
1462    }
1463    pub fn push_oifname_bytes(mut self, value: &[u8]) -> Self {
1464        push_header(self.as_vec_mut(), 17u16, (value.len() + 1) as u16);
1465        self.as_vec_mut().extend(value);
1466        self.as_vec_mut().push(0);
1467        self
1468    }
1469    pub fn push_pad(mut self, value: &[u8]) -> Self {
1470        push_header(self.as_vec_mut(), 18u16, value.len() as u16);
1471        self.as_vec_mut().extend(value);
1472        self
1473    }
1474    pub fn push_l3mdev(mut self, value: u8) -> Self {
1475        push_header(self.as_vec_mut(), 19u16, 1 as u16);
1476        self.as_vec_mut().extend(value.to_ne_bytes());
1477        self
1478    }
1479    pub fn push_uid_range(mut self, value: FibRuleUidRange) -> Self {
1480        push_header(self.as_vec_mut(), 20u16, value.as_slice().len() as u16);
1481        self.as_vec_mut().extend(value.as_slice());
1482        self
1483    }
1484    pub fn push_protocol(mut self, value: u8) -> Self {
1485        push_header(self.as_vec_mut(), 21u16, 1 as u16);
1486        self.as_vec_mut().extend(value.to_ne_bytes());
1487        self
1488    }
1489    pub fn push_ip_proto(mut self, value: u8) -> Self {
1490        push_header(self.as_vec_mut(), 22u16, 1 as u16);
1491        self.as_vec_mut().extend(value.to_ne_bytes());
1492        self
1493    }
1494    pub fn push_sport_range(mut self, value: FibRulePortRange) -> Self {
1495        push_header(self.as_vec_mut(), 23u16, value.as_slice().len() as u16);
1496        self.as_vec_mut().extend(value.as_slice());
1497        self
1498    }
1499    pub fn push_dport_range(mut self, value: FibRulePortRange) -> Self {
1500        push_header(self.as_vec_mut(), 24u16, value.as_slice().len() as u16);
1501        self.as_vec_mut().extend(value.as_slice());
1502        self
1503    }
1504    pub fn push_dscp(mut self, value: u8) -> Self {
1505        push_header(self.as_vec_mut(), 25u16, 1 as u16);
1506        self.as_vec_mut().extend(value.to_ne_bytes());
1507        self
1508    }
1509    pub fn push_flowlabel(mut self, value: u32) -> Self {
1510        push_header(self.as_vec_mut(), 26u16, 4 as u16);
1511        self.as_vec_mut().extend(value.to_be_bytes());
1512        self
1513    }
1514    pub fn push_flowlabel_mask(mut self, value: u32) -> Self {
1515        push_header(self.as_vec_mut(), 27u16, 4 as u16);
1516        self.as_vec_mut().extend(value.to_be_bytes());
1517        self
1518    }
1519    pub fn push_sport_mask(mut self, value: u16) -> Self {
1520        push_header(self.as_vec_mut(), 28u16, 2 as u16);
1521        self.as_vec_mut().extend(value.to_ne_bytes());
1522        self
1523    }
1524    pub fn push_dport_mask(mut self, value: u16) -> Self {
1525        push_header(self.as_vec_mut(), 29u16, 2 as u16);
1526        self.as_vec_mut().extend(value.to_ne_bytes());
1527        self
1528    }
1529    pub fn push_dscp_mask(mut self, value: u8) -> Self {
1530        push_header(self.as_vec_mut(), 30u16, 1 as u16);
1531        self.as_vec_mut().extend(value.to_ne_bytes());
1532        self
1533    }
1534}
1535impl<Prev: Pusher> Drop for PushFibRuleAttrs<Prev> {
1536    fn drop(&mut self) {
1537        if let Some(prev) = &mut self.prev {
1538            if let Some(header_offset) = &self.header_offset {
1539                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1540            }
1541        }
1542    }
1543}
1544#[doc = "Add new FIB rule\n\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\n"]
1545#[derive(Debug)]
1546pub struct OpNewruleDo<'r> {
1547    request: Request<'r>,
1548}
1549impl<'r> OpNewruleDo<'r> {
1550    pub fn new(mut request: Request<'r>, header: &FibRuleHdr) -> Self {
1551        Self::write_header(request.buf_mut(), header);
1552        Self { request: request }
1553    }
1554    pub fn encode_request<'buf>(
1555        buf: &'buf mut Vec<u8>,
1556        header: &FibRuleHdr,
1557    ) -> PushFibRuleAttrs<&'buf mut Vec<u8>> {
1558        Self::write_header(buf, header);
1559        PushFibRuleAttrs::new(buf)
1560    }
1561    pub fn encode(&mut self) -> PushFibRuleAttrs<&mut Vec<u8>> {
1562        PushFibRuleAttrs::new(self.request.buf_mut())
1563    }
1564    pub fn into_encoder(self) -> PushFibRuleAttrs<RequestBuf<'r>> {
1565        PushFibRuleAttrs::new(self.request.buf)
1566    }
1567    pub fn decode_request<'a>(buf: &'a [u8]) -> (FibRuleHdr, IterableFibRuleAttrs<'a>) {
1568        let (header, attrs) = buf.split_at(buf.len().min(FibRuleHdr::len()));
1569        (
1570            FibRuleHdr::new_from_slice(header).unwrap_or_default(),
1571            IterableFibRuleAttrs::with_loc(attrs, buf.as_ptr() as usize),
1572        )
1573    }
1574    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &FibRuleHdr) {
1575        prev.as_vec_mut().extend(header.as_slice());
1576    }
1577}
1578impl NetlinkRequest for OpNewruleDo<'_> {
1579    fn protocol(&self) -> Protocol {
1580        Protocol::Raw {
1581            protonum: 0u16,
1582            request_type: 32u16,
1583        }
1584    }
1585    fn flags(&self) -> u16 {
1586        self.request.flags
1587    }
1588    fn payload(&self) -> &[u8] {
1589        self.request.buf()
1590    }
1591    type ReplyType<'buf> = (FibRuleHdr, IterableFibRuleAttrs<'buf>);
1592    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1593        Self::decode_request(buf)
1594    }
1595    fn lookup(
1596        buf: &[u8],
1597        offset: usize,
1598        missing_type: Option<u16>,
1599    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1600        Self::decode_request(buf)
1601            .1
1602            .lookup_attr(offset, missing_type)
1603    }
1604}
1605#[doc = "Remove an existing FIB rule\n\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\n"]
1606#[derive(Debug)]
1607pub struct OpDelruleDo<'r> {
1608    request: Request<'r>,
1609}
1610impl<'r> OpDelruleDo<'r> {
1611    pub fn new(mut request: Request<'r>, header: &FibRuleHdr) -> Self {
1612        Self::write_header(request.buf_mut(), header);
1613        Self { request: request }
1614    }
1615    pub fn encode_request<'buf>(
1616        buf: &'buf mut Vec<u8>,
1617        header: &FibRuleHdr,
1618    ) -> PushFibRuleAttrs<&'buf mut Vec<u8>> {
1619        Self::write_header(buf, header);
1620        PushFibRuleAttrs::new(buf)
1621    }
1622    pub fn encode(&mut self) -> PushFibRuleAttrs<&mut Vec<u8>> {
1623        PushFibRuleAttrs::new(self.request.buf_mut())
1624    }
1625    pub fn into_encoder(self) -> PushFibRuleAttrs<RequestBuf<'r>> {
1626        PushFibRuleAttrs::new(self.request.buf)
1627    }
1628    pub fn decode_request<'a>(buf: &'a [u8]) -> (FibRuleHdr, IterableFibRuleAttrs<'a>) {
1629        let (header, attrs) = buf.split_at(buf.len().min(FibRuleHdr::len()));
1630        (
1631            FibRuleHdr::new_from_slice(header).unwrap_or_default(),
1632            IterableFibRuleAttrs::with_loc(attrs, buf.as_ptr() as usize),
1633        )
1634    }
1635    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &FibRuleHdr) {
1636        prev.as_vec_mut().extend(header.as_slice());
1637    }
1638}
1639impl NetlinkRequest for OpDelruleDo<'_> {
1640    fn protocol(&self) -> Protocol {
1641        Protocol::Raw {
1642            protonum: 0u16,
1643            request_type: 33u16,
1644        }
1645    }
1646    fn flags(&self) -> u16 {
1647        self.request.flags
1648    }
1649    fn payload(&self) -> &[u8] {
1650        self.request.buf()
1651    }
1652    type ReplyType<'buf> = (FibRuleHdr, IterableFibRuleAttrs<'buf>);
1653    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1654        Self::decode_request(buf)
1655    }
1656    fn lookup(
1657        buf: &[u8],
1658        offset: usize,
1659        missing_type: Option<u16>,
1660    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1661        Self::decode_request(buf)
1662            .1
1663            .lookup_attr(offset, missing_type)
1664    }
1665}
1666#[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\n"]
1667#[derive(Debug)]
1668pub struct OpGetruleDump<'r> {
1669    request: Request<'r>,
1670}
1671impl<'r> OpGetruleDump<'r> {
1672    pub fn new(mut request: Request<'r>, header: &FibRuleHdr) -> Self {
1673        Self::write_header(request.buf_mut(), header);
1674        Self {
1675            request: request.set_dump(),
1676        }
1677    }
1678    pub fn encode_request<'buf>(
1679        buf: &'buf mut Vec<u8>,
1680        header: &FibRuleHdr,
1681    ) -> PushFibRuleAttrs<&'buf mut Vec<u8>> {
1682        Self::write_header(buf, header);
1683        PushFibRuleAttrs::new(buf)
1684    }
1685    pub fn encode(&mut self) -> PushFibRuleAttrs<&mut Vec<u8>> {
1686        PushFibRuleAttrs::new(self.request.buf_mut())
1687    }
1688    pub fn into_encoder(self) -> PushFibRuleAttrs<RequestBuf<'r>> {
1689        PushFibRuleAttrs::new(self.request.buf)
1690    }
1691    pub fn decode_request<'a>(buf: &'a [u8]) -> (FibRuleHdr, IterableFibRuleAttrs<'a>) {
1692        let (header, attrs) = buf.split_at(buf.len().min(FibRuleHdr::len()));
1693        (
1694            FibRuleHdr::new_from_slice(header).unwrap_or_default(),
1695            IterableFibRuleAttrs::with_loc(attrs, buf.as_ptr() as usize),
1696        )
1697    }
1698    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &FibRuleHdr) {
1699        prev.as_vec_mut().extend(header.as_slice());
1700    }
1701}
1702impl NetlinkRequest for OpGetruleDump<'_> {
1703    fn protocol(&self) -> Protocol {
1704        Protocol::Raw {
1705            protonum: 0u16,
1706            request_type: 34u16,
1707        }
1708    }
1709    fn flags(&self) -> u16 {
1710        self.request.flags
1711    }
1712    fn payload(&self) -> &[u8] {
1713        self.request.buf()
1714    }
1715    type ReplyType<'buf> = (FibRuleHdr, IterableFibRuleAttrs<'buf>);
1716    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1717        Self::decode_request(buf)
1718    }
1719    fn lookup(
1720        buf: &[u8],
1721        offset: usize,
1722        missing_type: Option<u16>,
1723    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1724        Self::decode_request(buf)
1725            .1
1726            .lookup_attr(offset, missing_type)
1727    }
1728}
1729#[derive(Debug)]
1730pub struct ChainedFinal<'a> {
1731    inner: Chained<'a>,
1732}
1733#[derive(Debug)]
1734pub struct Chained<'a> {
1735    buf: RequestBuf<'a>,
1736    first_seq: u32,
1737    lookups: Vec<(&'static str, LookupFn)>,
1738    last_header_offset: usize,
1739    last_kind: Option<RequestInfo>,
1740}
1741impl<'a> ChainedFinal<'a> {
1742    pub fn into_chained(self) -> Chained<'a> {
1743        self.inner
1744    }
1745    pub fn buf(&self) -> &Vec<u8> {
1746        self.inner.buf()
1747    }
1748    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1749        self.inner.buf_mut()
1750    }
1751    fn get_index(&self, seq: u32) -> Option<u32> {
1752        let min = self.inner.first_seq;
1753        let max = min.wrapping_add(self.inner.lookups.len() as u32);
1754        return if min <= max {
1755            (min..max).contains(&seq).then(|| seq - min)
1756        } else if min <= seq {
1757            Some(seq - min)
1758        } else if seq < max {
1759            Some(u32::MAX - min + seq)
1760        } else {
1761            None
1762        };
1763    }
1764}
1765impl crate::traits::NetlinkChained for ChainedFinal<'_> {
1766    fn protonum(&self) -> u16 {
1767        PROTONUM
1768    }
1769    fn payload(&self) -> &[u8] {
1770        self.buf()
1771    }
1772    fn chain_len(&self) -> usize {
1773        self.inner.lookups.len()
1774    }
1775    fn get_index(&self, seq: u32) -> Option<usize> {
1776        self.get_index(seq).map(|n| n as usize)
1777    }
1778    fn name(&self, index: usize) -> &'static str {
1779        self.inner.lookups[index].0
1780    }
1781    fn lookup(&self, index: usize) -> LookupFn {
1782        self.inner.lookups[index].1
1783    }
1784}
1785impl Chained<'static> {
1786    pub fn new(first_seq: u32) -> Self {
1787        Self::new_from_buf(Vec::new(), first_seq)
1788    }
1789    pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
1790        Self {
1791            buf: RequestBuf::Own(buf),
1792            first_seq,
1793            lookups: Vec::new(),
1794            last_header_offset: 0,
1795            last_kind: None,
1796        }
1797    }
1798    pub fn into_buf(self) -> Vec<u8> {
1799        match self.buf {
1800            RequestBuf::Own(buf) => buf,
1801            _ => unreachable!(),
1802        }
1803    }
1804}
1805impl<'a> Chained<'a> {
1806    pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
1807        Self {
1808            buf: RequestBuf::Ref(buf),
1809            first_seq,
1810            lookups: Vec::new(),
1811            last_header_offset: 0,
1812            last_kind: None,
1813        }
1814    }
1815    pub fn finalize(mut self) -> ChainedFinal<'a> {
1816        self.update_header();
1817        ChainedFinal { inner: self }
1818    }
1819    pub fn request(&mut self) -> Request<'_> {
1820        self.update_header();
1821        self.last_header_offset = self.buf().len();
1822        self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
1823        let mut request = Request::new_extend(self.buf.buf_mut());
1824        self.last_kind = None;
1825        request.writeback = Some(&mut self.last_kind);
1826        request
1827    }
1828    pub fn buf(&self) -> &Vec<u8> {
1829        self.buf.buf()
1830    }
1831    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1832        self.buf.buf_mut()
1833    }
1834    fn update_header(&mut self) {
1835        let Some(RequestInfo {
1836            protocol,
1837            flags,
1838            name,
1839            lookup,
1840        }) = self.last_kind
1841        else {
1842            if !self.buf().is_empty() {
1843                assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
1844                self.buf.buf_mut().truncate(self.last_header_offset);
1845            }
1846            return;
1847        };
1848        let header_offset = self.last_header_offset;
1849        let request_type = match protocol {
1850            Protocol::Raw { request_type, .. } => request_type,
1851            Protocol::Generic(_) => unreachable!(),
1852        };
1853        let index = self.lookups.len();
1854        let seq = self.first_seq.wrapping_add(index as u32);
1855        self.lookups.push((name, lookup));
1856        let buf = self.buf_mut();
1857        align(buf);
1858        let header = Nlmsghdr {
1859            len: (buf.len() - header_offset) as u32,
1860            r#type: request_type,
1861            flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
1862            seq,
1863            pid: 0,
1864        };
1865        buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
1866    }
1867}
1868use crate::traits::LookupFn;
1869use crate::utils::RequestBuf;
1870#[derive(Debug)]
1871pub struct Request<'buf> {
1872    buf: RequestBuf<'buf>,
1873    flags: u16,
1874    writeback: Option<&'buf mut Option<RequestInfo>>,
1875}
1876#[allow(unused)]
1877#[derive(Debug, Clone)]
1878pub struct RequestInfo {
1879    protocol: Protocol,
1880    flags: u16,
1881    name: &'static str,
1882    lookup: LookupFn,
1883}
1884impl Request<'static> {
1885    pub fn new() -> Self {
1886        Self::new_from_buf(Vec::new())
1887    }
1888    pub fn new_from_buf(buf: Vec<u8>) -> Self {
1889        Self {
1890            flags: 0,
1891            buf: RequestBuf::Own(buf),
1892            writeback: None,
1893        }
1894    }
1895    pub fn into_buf(self) -> Vec<u8> {
1896        match self.buf {
1897            RequestBuf::Own(buf) => buf,
1898            _ => unreachable!(),
1899        }
1900    }
1901}
1902impl<'buf> Request<'buf> {
1903    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1904        buf.clear();
1905        Self::new_extend(buf)
1906    }
1907    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1908        Self {
1909            flags: 0,
1910            buf: RequestBuf::Ref(buf),
1911            writeback: None,
1912        }
1913    }
1914    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1915        let Some(writeback) = &mut self.writeback else {
1916            return;
1917        };
1918        **writeback = Some(RequestInfo {
1919            protocol,
1920            flags: self.flags,
1921            name,
1922            lookup,
1923        })
1924    }
1925    pub fn buf(&self) -> &Vec<u8> {
1926        self.buf.buf()
1927    }
1928    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1929        self.buf.buf_mut()
1930    }
1931    #[doc = "Set `NLM_F_CREATE` flag"]
1932    pub fn set_create(mut self) -> Self {
1933        self.flags |= consts::NLM_F_CREATE as u16;
1934        self
1935    }
1936    #[doc = "Set `NLM_F_EXCL` flag"]
1937    pub fn set_excl(mut self) -> Self {
1938        self.flags |= consts::NLM_F_EXCL as u16;
1939        self
1940    }
1941    #[doc = "Set `NLM_F_REPLACE` flag"]
1942    pub fn set_replace(mut self) -> Self {
1943        self.flags |= consts::NLM_F_REPLACE as u16;
1944        self
1945    }
1946    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1947    pub fn set_change(self) -> Self {
1948        self.set_create().set_replace()
1949    }
1950    #[doc = "Set `NLM_F_APPEND` flag"]
1951    pub fn set_append(mut self) -> Self {
1952        self.flags |= consts::NLM_F_APPEND as u16;
1953        self
1954    }
1955    #[doc = "Set `self.flags |= flags`"]
1956    pub fn set_flags(mut self, flags: u16) -> Self {
1957        self.flags |= flags;
1958        self
1959    }
1960    #[doc = "Set `self.flags ^= self.flags & flags`"]
1961    pub fn unset_flags(mut self, flags: u16) -> Self {
1962        self.flags ^= self.flags & flags;
1963        self
1964    }
1965    #[doc = "Set `NLM_F_DUMP` flag"]
1966    fn set_dump(mut self) -> Self {
1967        self.flags |= consts::NLM_F_DUMP as u16;
1968        self
1969    }
1970    #[doc = "Add new FIB rule\n\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\n"]
1971    pub fn op_newrule_do(self, header: &FibRuleHdr) -> OpNewruleDo<'buf> {
1972        let mut res = OpNewruleDo::new(self, header);
1973        res.request
1974            .do_writeback(res.protocol(), "op-newrule-do", OpNewruleDo::lookup);
1975        res
1976    }
1977    #[doc = "Remove an existing FIB rule\n\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\n"]
1978    pub fn op_delrule_do(self, header: &FibRuleHdr) -> OpDelruleDo<'buf> {
1979        let mut res = OpDelruleDo::new(self, header);
1980        res.request
1981            .do_writeback(res.protocol(), "op-delrule-do", OpDelruleDo::lookup);
1982        res
1983    }
1984    #[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\n"]
1985    pub fn op_getrule_dump(self, header: &FibRuleHdr) -> OpGetruleDump<'buf> {
1986        let mut res = OpGetruleDump::new(self, header);
1987        res.request
1988            .do_writeback(res.protocol(), "op-getrule-dump", OpGetruleDump::lookup);
1989        res
1990    }
1991}
1992#[cfg(test)]
1993mod generated_tests {
1994    use super::*;
1995    #[test]
1996    fn tests() {
1997        let _ = IterableFibRuleAttrs::get_dport_mask;
1998        let _ = IterableFibRuleAttrs::get_dport_range;
1999        let _ = IterableFibRuleAttrs::get_dscp;
2000        let _ = IterableFibRuleAttrs::get_dscp_mask;
2001        let _ = IterableFibRuleAttrs::get_flow;
2002        let _ = IterableFibRuleAttrs::get_flowlabel;
2003        let _ = IterableFibRuleAttrs::get_flowlabel_mask;
2004        let _ = IterableFibRuleAttrs::get_fwmark;
2005        let _ = IterableFibRuleAttrs::get_fwmask;
2006        let _ = IterableFibRuleAttrs::get_goto;
2007        let _ = IterableFibRuleAttrs::get_iifname;
2008        let _ = IterableFibRuleAttrs::get_ip_proto;
2009        let _ = IterableFibRuleAttrs::get_l3mdev;
2010        let _ = IterableFibRuleAttrs::get_oifname;
2011        let _ = IterableFibRuleAttrs::get_priority;
2012        let _ = IterableFibRuleAttrs::get_protocol;
2013        let _ = IterableFibRuleAttrs::get_sport_mask;
2014        let _ = IterableFibRuleAttrs::get_sport_range;
2015        let _ = IterableFibRuleAttrs::get_suppress_ifgroup;
2016        let _ = IterableFibRuleAttrs::get_suppress_prefixlen;
2017        let _ = IterableFibRuleAttrs::get_table;
2018        let _ = IterableFibRuleAttrs::get_tun_id;
2019        let _ = IterableFibRuleAttrs::get_uid_range;
2020        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_dport_mask;
2021        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_dport_range;
2022        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_dscp;
2023        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_dscp_mask;
2024        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_flow;
2025        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_flowlabel;
2026        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_flowlabel_mask;
2027        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_fwmark;
2028        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_fwmask;
2029        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_goto;
2030        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_iifname;
2031        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_ip_proto;
2032        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_l3mdev;
2033        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_oifname;
2034        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_priority;
2035        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_protocol;
2036        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_sport_mask;
2037        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_sport_range;
2038        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_suppress_ifgroup;
2039        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_suppress_prefixlen;
2040        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_table;
2041        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_tun_id;
2042        let _ = PushFibRuleAttrs::<&mut Vec<u8>>::push_uid_range;
2043    }
2044}