Skip to main content

netlink_bindings/rt-route/
mod.rs

1#![doc = "Route configuration 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-route";
17pub const PROTONAME_CSTR: &CStr = c"rt-route";
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 RtmType {
22    Unspec = 0,
23    Unicast = 1,
24    Local = 2,
25    Broadcast = 3,
26    Anycast = 4,
27    Multicast = 5,
28    Blackhole = 6,
29    Unreachable = 7,
30    Prohibit = 8,
31    Throw = 9,
32    Nat = 10,
33    Xresolve = 11,
34}
35impl RtmType {
36    pub fn from_value(value: u64) -> Option<Self> {
37        Some(match value {
38            0 => Self::Unspec,
39            1 => Self::Unicast,
40            2 => Self::Local,
41            3 => Self::Broadcast,
42            4 => Self::Anycast,
43            5 => Self::Multicast,
44            6 => Self::Blackhole,
45            7 => Self::Unreachable,
46            8 => Self::Prohibit,
47            9 => Self::Throw,
48            10 => Self::Nat,
49            11 => Self::Xresolve,
50            _ => return None,
51        })
52    }
53}
54#[repr(C, packed(4))]
55pub struct Rtmsg {
56    pub rtm_family: u8,
57    pub rtm_dst_len: u8,
58    pub rtm_src_len: u8,
59    pub rtm_tos: u8,
60    pub rtm_table: u8,
61    pub rtm_protocol: u8,
62    pub rtm_scope: u8,
63    #[doc = "Associated type: [`RtmType`] (enum)"]
64    pub rtm_type: u8,
65    pub rtm_flags: u32,
66}
67impl Clone for Rtmsg {
68    fn clone(&self) -> Self {
69        Self::new_from_array(*self.as_array())
70    }
71}
72#[doc = "Create zero-initialized struct"]
73impl Default for Rtmsg {
74    fn default() -> Self {
75        Self::new()
76    }
77}
78impl Rtmsg {
79    #[doc = "Create zero-initialized struct"]
80    pub fn new() -> Self {
81        Self::new_from_array([0u8; Self::len()])
82    }
83    #[doc = "Copy from contents from slice"]
84    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
85        if other.len() != Self::len() {
86            return None;
87        }
88        let mut buf = [0u8; Self::len()];
89        buf.clone_from_slice(other);
90        Some(Self::new_from_array(buf))
91    }
92    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
93    pub fn new_from_zeroed(other: &[u8]) -> Self {
94        let mut buf = [0u8; Self::len()];
95        let len = buf.len().min(other.len());
96        buf[..len].clone_from_slice(&other[..len]);
97        Self::new_from_array(buf)
98    }
99    pub fn new_from_array(buf: [u8; 12usize]) -> Self {
100        unsafe { std::mem::transmute(buf) }
101    }
102    pub fn as_slice(&self) -> &[u8] {
103        unsafe {
104            let ptr: *const u8 = std::mem::transmute(self as *const Self);
105            std::slice::from_raw_parts(ptr, Self::len())
106        }
107    }
108    pub fn from_slice(buf: &[u8]) -> &Self {
109        assert!(buf.len() >= Self::len());
110        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
111        unsafe { std::mem::transmute(buf.as_ptr()) }
112    }
113    pub fn as_array(&self) -> &[u8; 12usize] {
114        unsafe { std::mem::transmute(self) }
115    }
116    pub fn from_array(buf: &[u8; 12usize]) -> &Self {
117        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
118        unsafe { std::mem::transmute(buf) }
119    }
120    pub fn into_array(self) -> [u8; 12usize] {
121        unsafe { std::mem::transmute(self) }
122    }
123    pub const fn len() -> usize {
124        const _: () = assert!(std::mem::size_of::<Rtmsg>() == 12usize);
125        12usize
126    }
127}
128impl std::fmt::Debug for Rtmsg {
129    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130        fmt.debug_struct("Rtmsg")
131            .field("rtm_family", &self.rtm_family)
132            .field("rtm_dst_len", &self.rtm_dst_len)
133            .field("rtm_src_len", &self.rtm_src_len)
134            .field("rtm_tos", &self.rtm_tos)
135            .field("rtm_table", &self.rtm_table)
136            .field("rtm_protocol", &self.rtm_protocol)
137            .field("rtm_scope", &self.rtm_scope)
138            .field(
139                "rtm_type",
140                &FormatEnum(self.rtm_type.into(), RtmType::from_value),
141            )
142            .field("rtm_flags", &self.rtm_flags)
143            .finish()
144    }
145}
146#[derive(Debug)]
147#[repr(C, packed(4))]
148pub struct RtaCacheinfo {
149    pub rta_clntref: u32,
150    pub rta_lastuse: u32,
151    pub rta_expires: u32,
152    pub rta_error: u32,
153    pub rta_used: u32,
154}
155impl Clone for RtaCacheinfo {
156    fn clone(&self) -> Self {
157        Self::new_from_array(*self.as_array())
158    }
159}
160#[doc = "Create zero-initialized struct"]
161impl Default for RtaCacheinfo {
162    fn default() -> Self {
163        Self::new()
164    }
165}
166impl RtaCacheinfo {
167    #[doc = "Create zero-initialized struct"]
168    pub fn new() -> Self {
169        Self::new_from_array([0u8; Self::len()])
170    }
171    #[doc = "Copy from contents from slice"]
172    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
173        if other.len() != Self::len() {
174            return None;
175        }
176        let mut buf = [0u8; Self::len()];
177        buf.clone_from_slice(other);
178        Some(Self::new_from_array(buf))
179    }
180    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
181    pub fn new_from_zeroed(other: &[u8]) -> Self {
182        let mut buf = [0u8; Self::len()];
183        let len = buf.len().min(other.len());
184        buf[..len].clone_from_slice(&other[..len]);
185        Self::new_from_array(buf)
186    }
187    pub fn new_from_array(buf: [u8; 20usize]) -> Self {
188        unsafe { std::mem::transmute(buf) }
189    }
190    pub fn as_slice(&self) -> &[u8] {
191        unsafe {
192            let ptr: *const u8 = std::mem::transmute(self as *const Self);
193            std::slice::from_raw_parts(ptr, Self::len())
194        }
195    }
196    pub fn from_slice(buf: &[u8]) -> &Self {
197        assert!(buf.len() >= Self::len());
198        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
199        unsafe { std::mem::transmute(buf.as_ptr()) }
200    }
201    pub fn as_array(&self) -> &[u8; 20usize] {
202        unsafe { std::mem::transmute(self) }
203    }
204    pub fn from_array(buf: &[u8; 20usize]) -> &Self {
205        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
206        unsafe { std::mem::transmute(buf) }
207    }
208    pub fn into_array(self) -> [u8; 20usize] {
209        unsafe { std::mem::transmute(self) }
210    }
211    pub const fn len() -> usize {
212        const _: () = assert!(std::mem::size_of::<RtaCacheinfo>() == 20usize);
213        20usize
214    }
215}
216#[derive(Clone)]
217pub enum RouteAttrs<'a> {
218    Dst(std::net::IpAddr),
219    Src(std::net::IpAddr),
220    Iif(u32),
221    Oif(u32),
222    Gateway(std::net::IpAddr),
223    Priority(u32),
224    Prefsrc(std::net::IpAddr),
225    Metrics(IterableMetrics<'a>),
226    Multipath(&'a [u8]),
227    Protoinfo(&'a [u8]),
228    Flow(u32),
229    Cacheinfo(RtaCacheinfo),
230    Session(&'a [u8]),
231    MpAlgo(&'a [u8]),
232    Table(u32),
233    Mark(u32),
234    MfcStats(&'a [u8]),
235    Via(&'a [u8]),
236    Newdst(&'a [u8]),
237    Pref(u8),
238    EncapType(u16),
239    Encap(&'a [u8]),
240    Expires(u32),
241    Pad(&'a [u8]),
242    Uid(u32),
243    TtlPropagate(u8),
244    IpProto(u8),
245    Sport(u16),
246    Dport(u16),
247    NhId(u32),
248    Flowlabel(u32),
249}
250impl<'a> IterableRouteAttrs<'a> {
251    pub fn get_dst(&self) -> Result<std::net::IpAddr, ErrorContext> {
252        let mut iter = self.clone();
253        iter.pos = 0;
254        for attr in iter {
255            if let RouteAttrs::Dst(val) = attr? {
256                return Ok(val);
257            }
258        }
259        Err(ErrorContext::new_missing(
260            "RouteAttrs",
261            "Dst",
262            self.orig_loc,
263            self.buf.as_ptr() as usize,
264        ))
265    }
266    pub fn get_src(&self) -> Result<std::net::IpAddr, ErrorContext> {
267        let mut iter = self.clone();
268        iter.pos = 0;
269        for attr in iter {
270            if let RouteAttrs::Src(val) = attr? {
271                return Ok(val);
272            }
273        }
274        Err(ErrorContext::new_missing(
275            "RouteAttrs",
276            "Src",
277            self.orig_loc,
278            self.buf.as_ptr() as usize,
279        ))
280    }
281    pub fn get_iif(&self) -> Result<u32, ErrorContext> {
282        let mut iter = self.clone();
283        iter.pos = 0;
284        for attr in iter {
285            if let RouteAttrs::Iif(val) = attr? {
286                return Ok(val);
287            }
288        }
289        Err(ErrorContext::new_missing(
290            "RouteAttrs",
291            "Iif",
292            self.orig_loc,
293            self.buf.as_ptr() as usize,
294        ))
295    }
296    pub fn get_oif(&self) -> Result<u32, ErrorContext> {
297        let mut iter = self.clone();
298        iter.pos = 0;
299        for attr in iter {
300            if let RouteAttrs::Oif(val) = attr? {
301                return Ok(val);
302            }
303        }
304        Err(ErrorContext::new_missing(
305            "RouteAttrs",
306            "Oif",
307            self.orig_loc,
308            self.buf.as_ptr() as usize,
309        ))
310    }
311    pub fn get_gateway(&self) -> Result<std::net::IpAddr, ErrorContext> {
312        let mut iter = self.clone();
313        iter.pos = 0;
314        for attr in iter {
315            if let RouteAttrs::Gateway(val) = attr? {
316                return Ok(val);
317            }
318        }
319        Err(ErrorContext::new_missing(
320            "RouteAttrs",
321            "Gateway",
322            self.orig_loc,
323            self.buf.as_ptr() as usize,
324        ))
325    }
326    pub fn get_priority(&self) -> Result<u32, ErrorContext> {
327        let mut iter = self.clone();
328        iter.pos = 0;
329        for attr in iter {
330            if let RouteAttrs::Priority(val) = attr? {
331                return Ok(val);
332            }
333        }
334        Err(ErrorContext::new_missing(
335            "RouteAttrs",
336            "Priority",
337            self.orig_loc,
338            self.buf.as_ptr() as usize,
339        ))
340    }
341    pub fn get_prefsrc(&self) -> Result<std::net::IpAddr, ErrorContext> {
342        let mut iter = self.clone();
343        iter.pos = 0;
344        for attr in iter {
345            if let RouteAttrs::Prefsrc(val) = attr? {
346                return Ok(val);
347            }
348        }
349        Err(ErrorContext::new_missing(
350            "RouteAttrs",
351            "Prefsrc",
352            self.orig_loc,
353            self.buf.as_ptr() as usize,
354        ))
355    }
356    pub fn get_metrics(&self) -> Result<IterableMetrics<'a>, ErrorContext> {
357        let mut iter = self.clone();
358        iter.pos = 0;
359        for attr in iter {
360            if let RouteAttrs::Metrics(val) = attr? {
361                return Ok(val);
362            }
363        }
364        Err(ErrorContext::new_missing(
365            "RouteAttrs",
366            "Metrics",
367            self.orig_loc,
368            self.buf.as_ptr() as usize,
369        ))
370    }
371    pub fn get_multipath(&self) -> Result<&'a [u8], ErrorContext> {
372        let mut iter = self.clone();
373        iter.pos = 0;
374        for attr in iter {
375            if let RouteAttrs::Multipath(val) = attr? {
376                return Ok(val);
377            }
378        }
379        Err(ErrorContext::new_missing(
380            "RouteAttrs",
381            "Multipath",
382            self.orig_loc,
383            self.buf.as_ptr() as usize,
384        ))
385    }
386    pub fn get_protoinfo(&self) -> Result<&'a [u8], ErrorContext> {
387        let mut iter = self.clone();
388        iter.pos = 0;
389        for attr in iter {
390            if let RouteAttrs::Protoinfo(val) = attr? {
391                return Ok(val);
392            }
393        }
394        Err(ErrorContext::new_missing(
395            "RouteAttrs",
396            "Protoinfo",
397            self.orig_loc,
398            self.buf.as_ptr() as usize,
399        ))
400    }
401    pub fn get_flow(&self) -> Result<u32, ErrorContext> {
402        let mut iter = self.clone();
403        iter.pos = 0;
404        for attr in iter {
405            if let RouteAttrs::Flow(val) = attr? {
406                return Ok(val);
407            }
408        }
409        Err(ErrorContext::new_missing(
410            "RouteAttrs",
411            "Flow",
412            self.orig_loc,
413            self.buf.as_ptr() as usize,
414        ))
415    }
416    pub fn get_cacheinfo(&self) -> Result<RtaCacheinfo, ErrorContext> {
417        let mut iter = self.clone();
418        iter.pos = 0;
419        for attr in iter {
420            if let RouteAttrs::Cacheinfo(val) = attr? {
421                return Ok(val);
422            }
423        }
424        Err(ErrorContext::new_missing(
425            "RouteAttrs",
426            "Cacheinfo",
427            self.orig_loc,
428            self.buf.as_ptr() as usize,
429        ))
430    }
431    pub fn get_session(&self) -> Result<&'a [u8], ErrorContext> {
432        let mut iter = self.clone();
433        iter.pos = 0;
434        for attr in iter {
435            if let RouteAttrs::Session(val) = attr? {
436                return Ok(val);
437            }
438        }
439        Err(ErrorContext::new_missing(
440            "RouteAttrs",
441            "Session",
442            self.orig_loc,
443            self.buf.as_ptr() as usize,
444        ))
445    }
446    pub fn get_mp_algo(&self) -> Result<&'a [u8], ErrorContext> {
447        let mut iter = self.clone();
448        iter.pos = 0;
449        for attr in iter {
450            if let RouteAttrs::MpAlgo(val) = attr? {
451                return Ok(val);
452            }
453        }
454        Err(ErrorContext::new_missing(
455            "RouteAttrs",
456            "MpAlgo",
457            self.orig_loc,
458            self.buf.as_ptr() as usize,
459        ))
460    }
461    pub fn get_table(&self) -> Result<u32, ErrorContext> {
462        let mut iter = self.clone();
463        iter.pos = 0;
464        for attr in iter {
465            if let RouteAttrs::Table(val) = attr? {
466                return Ok(val);
467            }
468        }
469        Err(ErrorContext::new_missing(
470            "RouteAttrs",
471            "Table",
472            self.orig_loc,
473            self.buf.as_ptr() as usize,
474        ))
475    }
476    pub fn get_mark(&self) -> Result<u32, ErrorContext> {
477        let mut iter = self.clone();
478        iter.pos = 0;
479        for attr in iter {
480            if let RouteAttrs::Mark(val) = attr? {
481                return Ok(val);
482            }
483        }
484        Err(ErrorContext::new_missing(
485            "RouteAttrs",
486            "Mark",
487            self.orig_loc,
488            self.buf.as_ptr() as usize,
489        ))
490    }
491    pub fn get_mfc_stats(&self) -> Result<&'a [u8], ErrorContext> {
492        let mut iter = self.clone();
493        iter.pos = 0;
494        for attr in iter {
495            if let RouteAttrs::MfcStats(val) = attr? {
496                return Ok(val);
497            }
498        }
499        Err(ErrorContext::new_missing(
500            "RouteAttrs",
501            "MfcStats",
502            self.orig_loc,
503            self.buf.as_ptr() as usize,
504        ))
505    }
506    pub fn get_via(&self) -> Result<&'a [u8], ErrorContext> {
507        let mut iter = self.clone();
508        iter.pos = 0;
509        for attr in iter {
510            if let RouteAttrs::Via(val) = attr? {
511                return Ok(val);
512            }
513        }
514        Err(ErrorContext::new_missing(
515            "RouteAttrs",
516            "Via",
517            self.orig_loc,
518            self.buf.as_ptr() as usize,
519        ))
520    }
521    pub fn get_newdst(&self) -> Result<&'a [u8], ErrorContext> {
522        let mut iter = self.clone();
523        iter.pos = 0;
524        for attr in iter {
525            if let RouteAttrs::Newdst(val) = attr? {
526                return Ok(val);
527            }
528        }
529        Err(ErrorContext::new_missing(
530            "RouteAttrs",
531            "Newdst",
532            self.orig_loc,
533            self.buf.as_ptr() as usize,
534        ))
535    }
536    pub fn get_pref(&self) -> Result<u8, ErrorContext> {
537        let mut iter = self.clone();
538        iter.pos = 0;
539        for attr in iter {
540            if let RouteAttrs::Pref(val) = attr? {
541                return Ok(val);
542            }
543        }
544        Err(ErrorContext::new_missing(
545            "RouteAttrs",
546            "Pref",
547            self.orig_loc,
548            self.buf.as_ptr() as usize,
549        ))
550    }
551    pub fn get_encap_type(&self) -> Result<u16, ErrorContext> {
552        let mut iter = self.clone();
553        iter.pos = 0;
554        for attr in iter {
555            if let RouteAttrs::EncapType(val) = attr? {
556                return Ok(val);
557            }
558        }
559        Err(ErrorContext::new_missing(
560            "RouteAttrs",
561            "EncapType",
562            self.orig_loc,
563            self.buf.as_ptr() as usize,
564        ))
565    }
566    pub fn get_encap(&self) -> Result<&'a [u8], ErrorContext> {
567        let mut iter = self.clone();
568        iter.pos = 0;
569        for attr in iter {
570            if let RouteAttrs::Encap(val) = attr? {
571                return Ok(val);
572            }
573        }
574        Err(ErrorContext::new_missing(
575            "RouteAttrs",
576            "Encap",
577            self.orig_loc,
578            self.buf.as_ptr() as usize,
579        ))
580    }
581    pub fn get_expires(&self) -> Result<u32, ErrorContext> {
582        let mut iter = self.clone();
583        iter.pos = 0;
584        for attr in iter {
585            if let RouteAttrs::Expires(val) = attr? {
586                return Ok(val);
587            }
588        }
589        Err(ErrorContext::new_missing(
590            "RouteAttrs",
591            "Expires",
592            self.orig_loc,
593            self.buf.as_ptr() as usize,
594        ))
595    }
596    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
597        let mut iter = self.clone();
598        iter.pos = 0;
599        for attr in iter {
600            if let RouteAttrs::Pad(val) = attr? {
601                return Ok(val);
602            }
603        }
604        Err(ErrorContext::new_missing(
605            "RouteAttrs",
606            "Pad",
607            self.orig_loc,
608            self.buf.as_ptr() as usize,
609        ))
610    }
611    pub fn get_uid(&self) -> Result<u32, ErrorContext> {
612        let mut iter = self.clone();
613        iter.pos = 0;
614        for attr in iter {
615            if let RouteAttrs::Uid(val) = attr? {
616                return Ok(val);
617            }
618        }
619        Err(ErrorContext::new_missing(
620            "RouteAttrs",
621            "Uid",
622            self.orig_loc,
623            self.buf.as_ptr() as usize,
624        ))
625    }
626    pub fn get_ttl_propagate(&self) -> Result<u8, ErrorContext> {
627        let mut iter = self.clone();
628        iter.pos = 0;
629        for attr in iter {
630            if let RouteAttrs::TtlPropagate(val) = attr? {
631                return Ok(val);
632            }
633        }
634        Err(ErrorContext::new_missing(
635            "RouteAttrs",
636            "TtlPropagate",
637            self.orig_loc,
638            self.buf.as_ptr() as usize,
639        ))
640    }
641    pub fn get_ip_proto(&self) -> Result<u8, ErrorContext> {
642        let mut iter = self.clone();
643        iter.pos = 0;
644        for attr in iter {
645            if let RouteAttrs::IpProto(val) = attr? {
646                return Ok(val);
647            }
648        }
649        Err(ErrorContext::new_missing(
650            "RouteAttrs",
651            "IpProto",
652            self.orig_loc,
653            self.buf.as_ptr() as usize,
654        ))
655    }
656    pub fn get_sport(&self) -> Result<u16, ErrorContext> {
657        let mut iter = self.clone();
658        iter.pos = 0;
659        for attr in iter {
660            if let RouteAttrs::Sport(val) = attr? {
661                return Ok(val);
662            }
663        }
664        Err(ErrorContext::new_missing(
665            "RouteAttrs",
666            "Sport",
667            self.orig_loc,
668            self.buf.as_ptr() as usize,
669        ))
670    }
671    pub fn get_dport(&self) -> Result<u16, ErrorContext> {
672        let mut iter = self.clone();
673        iter.pos = 0;
674        for attr in iter {
675            if let RouteAttrs::Dport(val) = attr? {
676                return Ok(val);
677            }
678        }
679        Err(ErrorContext::new_missing(
680            "RouteAttrs",
681            "Dport",
682            self.orig_loc,
683            self.buf.as_ptr() as usize,
684        ))
685    }
686    pub fn get_nh_id(&self) -> Result<u32, ErrorContext> {
687        let mut iter = self.clone();
688        iter.pos = 0;
689        for attr in iter {
690            if let RouteAttrs::NhId(val) = attr? {
691                return Ok(val);
692            }
693        }
694        Err(ErrorContext::new_missing(
695            "RouteAttrs",
696            "NhId",
697            self.orig_loc,
698            self.buf.as_ptr() as usize,
699        ))
700    }
701    pub fn get_flowlabel(&self) -> Result<u32, ErrorContext> {
702        let mut iter = self.clone();
703        iter.pos = 0;
704        for attr in iter {
705            if let RouteAttrs::Flowlabel(val) = attr? {
706                return Ok(val);
707            }
708        }
709        Err(ErrorContext::new_missing(
710            "RouteAttrs",
711            "Flowlabel",
712            self.orig_loc,
713            self.buf.as_ptr() as usize,
714        ))
715    }
716}
717impl RouteAttrs<'_> {
718    pub fn new<'a>(buf: &'a [u8]) -> IterableRouteAttrs<'a> {
719        IterableRouteAttrs::with_loc(buf, buf.as_ptr() as usize)
720    }
721    fn attr_from_type(r#type: u16) -> Option<&'static str> {
722        let res = match r#type {
723            1u16 => "Dst",
724            2u16 => "Src",
725            3u16 => "Iif",
726            4u16 => "Oif",
727            5u16 => "Gateway",
728            6u16 => "Priority",
729            7u16 => "Prefsrc",
730            8u16 => "Metrics",
731            9u16 => "Multipath",
732            10u16 => "Protoinfo",
733            11u16 => "Flow",
734            12u16 => "Cacheinfo",
735            13u16 => "Session",
736            14u16 => "MpAlgo",
737            15u16 => "Table",
738            16u16 => "Mark",
739            17u16 => "MfcStats",
740            18u16 => "Via",
741            19u16 => "Newdst",
742            20u16 => "Pref",
743            21u16 => "EncapType",
744            22u16 => "Encap",
745            23u16 => "Expires",
746            24u16 => "Pad",
747            25u16 => "Uid",
748            26u16 => "TtlPropagate",
749            27u16 => "IpProto",
750            28u16 => "Sport",
751            29u16 => "Dport",
752            30u16 => "NhId",
753            31u16 => "Flowlabel",
754            _ => return None,
755        };
756        Some(res)
757    }
758}
759#[derive(Clone, Copy, Default)]
760pub struct IterableRouteAttrs<'a> {
761    buf: &'a [u8],
762    pos: usize,
763    orig_loc: usize,
764}
765impl<'a> IterableRouteAttrs<'a> {
766    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
767        Self {
768            buf,
769            pos: 0,
770            orig_loc,
771        }
772    }
773    pub fn get_buf(&self) -> &'a [u8] {
774        self.buf
775    }
776}
777impl<'a> Iterator for IterableRouteAttrs<'a> {
778    type Item = Result<RouteAttrs<'a>, ErrorContext>;
779    fn next(&mut self) -> Option<Self::Item> {
780        let pos = self.pos;
781        let mut r#type;
782        loop {
783            r#type = None;
784            if self.buf.len() == self.pos {
785                return None;
786            }
787            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
788                break;
789            };
790            r#type = Some(header.r#type);
791            let res = match header.r#type {
792                1u16 => RouteAttrs::Dst({
793                    let res = parse_ip(next);
794                    let Some(val) = res else { break };
795                    val
796                }),
797                2u16 => RouteAttrs::Src({
798                    let res = parse_ip(next);
799                    let Some(val) = res else { break };
800                    val
801                }),
802                3u16 => RouteAttrs::Iif({
803                    let res = parse_u32(next);
804                    let Some(val) = res else { break };
805                    val
806                }),
807                4u16 => RouteAttrs::Oif({
808                    let res = parse_u32(next);
809                    let Some(val) = res else { break };
810                    val
811                }),
812                5u16 => RouteAttrs::Gateway({
813                    let res = parse_ip(next);
814                    let Some(val) = res else { break };
815                    val
816                }),
817                6u16 => RouteAttrs::Priority({
818                    let res = parse_u32(next);
819                    let Some(val) = res else { break };
820                    val
821                }),
822                7u16 => RouteAttrs::Prefsrc({
823                    let res = parse_ip(next);
824                    let Some(val) = res else { break };
825                    val
826                }),
827                8u16 => RouteAttrs::Metrics({
828                    let res = Some(IterableMetrics::with_loc(next, self.orig_loc));
829                    let Some(val) = res else { break };
830                    val
831                }),
832                9u16 => RouteAttrs::Multipath({
833                    let res = Some(next);
834                    let Some(val) = res else { break };
835                    val
836                }),
837                10u16 => RouteAttrs::Protoinfo({
838                    let res = Some(next);
839                    let Some(val) = res else { break };
840                    val
841                }),
842                11u16 => RouteAttrs::Flow({
843                    let res = parse_u32(next);
844                    let Some(val) = res else { break };
845                    val
846                }),
847                12u16 => RouteAttrs::Cacheinfo({
848                    let res = Some(RtaCacheinfo::new_from_zeroed(next));
849                    let Some(val) = res else { break };
850                    val
851                }),
852                13u16 => RouteAttrs::Session({
853                    let res = Some(next);
854                    let Some(val) = res else { break };
855                    val
856                }),
857                14u16 => RouteAttrs::MpAlgo({
858                    let res = Some(next);
859                    let Some(val) = res else { break };
860                    val
861                }),
862                15u16 => RouteAttrs::Table({
863                    let res = parse_u32(next);
864                    let Some(val) = res else { break };
865                    val
866                }),
867                16u16 => RouteAttrs::Mark({
868                    let res = parse_u32(next);
869                    let Some(val) = res else { break };
870                    val
871                }),
872                17u16 => RouteAttrs::MfcStats({
873                    let res = Some(next);
874                    let Some(val) = res else { break };
875                    val
876                }),
877                18u16 => RouteAttrs::Via({
878                    let res = Some(next);
879                    let Some(val) = res else { break };
880                    val
881                }),
882                19u16 => RouteAttrs::Newdst({
883                    let res = Some(next);
884                    let Some(val) = res else { break };
885                    val
886                }),
887                20u16 => RouteAttrs::Pref({
888                    let res = parse_u8(next);
889                    let Some(val) = res else { break };
890                    val
891                }),
892                21u16 => RouteAttrs::EncapType({
893                    let res = parse_u16(next);
894                    let Some(val) = res else { break };
895                    val
896                }),
897                22u16 => RouteAttrs::Encap({
898                    let res = Some(next);
899                    let Some(val) = res else { break };
900                    val
901                }),
902                23u16 => RouteAttrs::Expires({
903                    let res = parse_u32(next);
904                    let Some(val) = res else { break };
905                    val
906                }),
907                24u16 => RouteAttrs::Pad({
908                    let res = Some(next);
909                    let Some(val) = res else { break };
910                    val
911                }),
912                25u16 => RouteAttrs::Uid({
913                    let res = parse_u32(next);
914                    let Some(val) = res else { break };
915                    val
916                }),
917                26u16 => RouteAttrs::TtlPropagate({
918                    let res = parse_u8(next);
919                    let Some(val) = res else { break };
920                    val
921                }),
922                27u16 => RouteAttrs::IpProto({
923                    let res = parse_u8(next);
924                    let Some(val) = res else { break };
925                    val
926                }),
927                28u16 => RouteAttrs::Sport({
928                    let res = parse_u16(next);
929                    let Some(val) = res else { break };
930                    val
931                }),
932                29u16 => RouteAttrs::Dport({
933                    let res = parse_u16(next);
934                    let Some(val) = res else { break };
935                    val
936                }),
937                30u16 => RouteAttrs::NhId({
938                    let res = parse_u32(next);
939                    let Some(val) = res else { break };
940                    val
941                }),
942                31u16 => RouteAttrs::Flowlabel({
943                    let res = parse_be_u32(next);
944                    let Some(val) = res else { break };
945                    val
946                }),
947                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
948                n => continue,
949            };
950            return Some(Ok(res));
951        }
952        Some(Err(ErrorContext::new(
953            "RouteAttrs",
954            r#type.and_then(|t| RouteAttrs::attr_from_type(t)),
955            self.orig_loc,
956            self.buf.as_ptr().wrapping_add(pos) as usize,
957        )))
958    }
959}
960impl<'a> std::fmt::Debug for IterableRouteAttrs<'_> {
961    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
962        let mut fmt = f.debug_struct("RouteAttrs");
963        for attr in self.clone() {
964            let attr = match attr {
965                Ok(a) => a,
966                Err(err) => {
967                    fmt.finish()?;
968                    f.write_str("Err(")?;
969                    err.fmt(f)?;
970                    return f.write_str(")");
971                }
972            };
973            match attr {
974                RouteAttrs::Dst(val) => fmt.field("Dst", &val),
975                RouteAttrs::Src(val) => fmt.field("Src", &val),
976                RouteAttrs::Iif(val) => fmt.field("Iif", &val),
977                RouteAttrs::Oif(val) => fmt.field("Oif", &val),
978                RouteAttrs::Gateway(val) => fmt.field("Gateway", &val),
979                RouteAttrs::Priority(val) => fmt.field("Priority", &val),
980                RouteAttrs::Prefsrc(val) => fmt.field("Prefsrc", &val),
981                RouteAttrs::Metrics(val) => fmt.field("Metrics", &val),
982                RouteAttrs::Multipath(val) => fmt.field("Multipath", &val),
983                RouteAttrs::Protoinfo(val) => fmt.field("Protoinfo", &val),
984                RouteAttrs::Flow(val) => fmt.field("Flow", &val),
985                RouteAttrs::Cacheinfo(val) => fmt.field("Cacheinfo", &val),
986                RouteAttrs::Session(val) => fmt.field("Session", &val),
987                RouteAttrs::MpAlgo(val) => fmt.field("MpAlgo", &val),
988                RouteAttrs::Table(val) => fmt.field("Table", &val),
989                RouteAttrs::Mark(val) => fmt.field("Mark", &val),
990                RouteAttrs::MfcStats(val) => fmt.field("MfcStats", &val),
991                RouteAttrs::Via(val) => fmt.field("Via", &val),
992                RouteAttrs::Newdst(val) => fmt.field("Newdst", &val),
993                RouteAttrs::Pref(val) => fmt.field("Pref", &val),
994                RouteAttrs::EncapType(val) => fmt.field("EncapType", &val),
995                RouteAttrs::Encap(val) => fmt.field("Encap", &val),
996                RouteAttrs::Expires(val) => fmt.field("Expires", &val),
997                RouteAttrs::Pad(val) => fmt.field("Pad", &val),
998                RouteAttrs::Uid(val) => fmt.field("Uid", &val),
999                RouteAttrs::TtlPropagate(val) => fmt.field("TtlPropagate", &val),
1000                RouteAttrs::IpProto(val) => fmt.field("IpProto", &val),
1001                RouteAttrs::Sport(val) => fmt.field("Sport", &val),
1002                RouteAttrs::Dport(val) => fmt.field("Dport", &val),
1003                RouteAttrs::NhId(val) => fmt.field("NhId", &val),
1004                RouteAttrs::Flowlabel(val) => fmt.field("Flowlabel", &val),
1005            };
1006        }
1007        fmt.finish()
1008    }
1009}
1010impl IterableRouteAttrs<'_> {
1011    pub fn lookup_attr(
1012        &self,
1013        offset: usize,
1014        missing_type: Option<u16>,
1015    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1016        let mut stack = Vec::new();
1017        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1018        if missing_type.is_some() && cur == offset {
1019            stack.push(("RouteAttrs", offset));
1020            return (
1021                stack,
1022                missing_type.and_then(|t| RouteAttrs::attr_from_type(t)),
1023            );
1024        }
1025        if cur > offset || cur + self.buf.len() < offset {
1026            return (stack, None);
1027        }
1028        let mut attrs = self.clone();
1029        let mut last_off = cur + attrs.pos;
1030        let mut missing = None;
1031        while let Some(attr) = attrs.next() {
1032            let Ok(attr) = attr else { break };
1033            match attr {
1034                RouteAttrs::Dst(val) => {
1035                    if last_off == offset {
1036                        stack.push(("Dst", last_off));
1037                        break;
1038                    }
1039                }
1040                RouteAttrs::Src(val) => {
1041                    if last_off == offset {
1042                        stack.push(("Src", last_off));
1043                        break;
1044                    }
1045                }
1046                RouteAttrs::Iif(val) => {
1047                    if last_off == offset {
1048                        stack.push(("Iif", last_off));
1049                        break;
1050                    }
1051                }
1052                RouteAttrs::Oif(val) => {
1053                    if last_off == offset {
1054                        stack.push(("Oif", last_off));
1055                        break;
1056                    }
1057                }
1058                RouteAttrs::Gateway(val) => {
1059                    if last_off == offset {
1060                        stack.push(("Gateway", last_off));
1061                        break;
1062                    }
1063                }
1064                RouteAttrs::Priority(val) => {
1065                    if last_off == offset {
1066                        stack.push(("Priority", last_off));
1067                        break;
1068                    }
1069                }
1070                RouteAttrs::Prefsrc(val) => {
1071                    if last_off == offset {
1072                        stack.push(("Prefsrc", last_off));
1073                        break;
1074                    }
1075                }
1076                RouteAttrs::Metrics(val) => {
1077                    (stack, missing) = val.lookup_attr(offset, missing_type);
1078                    if !stack.is_empty() {
1079                        break;
1080                    }
1081                }
1082                RouteAttrs::Multipath(val) => {
1083                    if last_off == offset {
1084                        stack.push(("Multipath", last_off));
1085                        break;
1086                    }
1087                }
1088                RouteAttrs::Protoinfo(val) => {
1089                    if last_off == offset {
1090                        stack.push(("Protoinfo", last_off));
1091                        break;
1092                    }
1093                }
1094                RouteAttrs::Flow(val) => {
1095                    if last_off == offset {
1096                        stack.push(("Flow", last_off));
1097                        break;
1098                    }
1099                }
1100                RouteAttrs::Cacheinfo(val) => {
1101                    if last_off == offset {
1102                        stack.push(("Cacheinfo", last_off));
1103                        break;
1104                    }
1105                }
1106                RouteAttrs::Session(val) => {
1107                    if last_off == offset {
1108                        stack.push(("Session", last_off));
1109                        break;
1110                    }
1111                }
1112                RouteAttrs::MpAlgo(val) => {
1113                    if last_off == offset {
1114                        stack.push(("MpAlgo", last_off));
1115                        break;
1116                    }
1117                }
1118                RouteAttrs::Table(val) => {
1119                    if last_off == offset {
1120                        stack.push(("Table", last_off));
1121                        break;
1122                    }
1123                }
1124                RouteAttrs::Mark(val) => {
1125                    if last_off == offset {
1126                        stack.push(("Mark", last_off));
1127                        break;
1128                    }
1129                }
1130                RouteAttrs::MfcStats(val) => {
1131                    if last_off == offset {
1132                        stack.push(("MfcStats", last_off));
1133                        break;
1134                    }
1135                }
1136                RouteAttrs::Via(val) => {
1137                    if last_off == offset {
1138                        stack.push(("Via", last_off));
1139                        break;
1140                    }
1141                }
1142                RouteAttrs::Newdst(val) => {
1143                    if last_off == offset {
1144                        stack.push(("Newdst", last_off));
1145                        break;
1146                    }
1147                }
1148                RouteAttrs::Pref(val) => {
1149                    if last_off == offset {
1150                        stack.push(("Pref", last_off));
1151                        break;
1152                    }
1153                }
1154                RouteAttrs::EncapType(val) => {
1155                    if last_off == offset {
1156                        stack.push(("EncapType", last_off));
1157                        break;
1158                    }
1159                }
1160                RouteAttrs::Encap(val) => {
1161                    if last_off == offset {
1162                        stack.push(("Encap", last_off));
1163                        break;
1164                    }
1165                }
1166                RouteAttrs::Expires(val) => {
1167                    if last_off == offset {
1168                        stack.push(("Expires", last_off));
1169                        break;
1170                    }
1171                }
1172                RouteAttrs::Pad(val) => {
1173                    if last_off == offset {
1174                        stack.push(("Pad", last_off));
1175                        break;
1176                    }
1177                }
1178                RouteAttrs::Uid(val) => {
1179                    if last_off == offset {
1180                        stack.push(("Uid", last_off));
1181                        break;
1182                    }
1183                }
1184                RouteAttrs::TtlPropagate(val) => {
1185                    if last_off == offset {
1186                        stack.push(("TtlPropagate", last_off));
1187                        break;
1188                    }
1189                }
1190                RouteAttrs::IpProto(val) => {
1191                    if last_off == offset {
1192                        stack.push(("IpProto", last_off));
1193                        break;
1194                    }
1195                }
1196                RouteAttrs::Sport(val) => {
1197                    if last_off == offset {
1198                        stack.push(("Sport", last_off));
1199                        break;
1200                    }
1201                }
1202                RouteAttrs::Dport(val) => {
1203                    if last_off == offset {
1204                        stack.push(("Dport", last_off));
1205                        break;
1206                    }
1207                }
1208                RouteAttrs::NhId(val) => {
1209                    if last_off == offset {
1210                        stack.push(("NhId", last_off));
1211                        break;
1212                    }
1213                }
1214                RouteAttrs::Flowlabel(val) => {
1215                    if last_off == offset {
1216                        stack.push(("Flowlabel", last_off));
1217                        break;
1218                    }
1219                }
1220                _ => {}
1221            };
1222            last_off = cur + attrs.pos;
1223        }
1224        if !stack.is_empty() {
1225            stack.push(("RouteAttrs", cur));
1226        }
1227        (stack, missing)
1228    }
1229}
1230#[derive(Clone)]
1231pub enum Metrics<'a> {
1232    Lock(u32),
1233    Mtu(u32),
1234    Window(u32),
1235    Rtt(u32),
1236    Rttvar(u32),
1237    Ssthresh(u32),
1238    Cwnd(u32),
1239    Advmss(u32),
1240    Reordering(u32),
1241    Hoplimit(u32),
1242    Initcwnd(u32),
1243    Features(u32),
1244    RtoMin(u32),
1245    Initrwnd(u32),
1246    Quickack(u32),
1247    CcAlgo(&'a CStr),
1248    FastopenNoCookie(u32),
1249}
1250impl<'a> IterableMetrics<'a> {
1251    pub fn get_lock(&self) -> Result<u32, ErrorContext> {
1252        let mut iter = self.clone();
1253        iter.pos = 0;
1254        for attr in iter {
1255            if let Metrics::Lock(val) = attr? {
1256                return Ok(val);
1257            }
1258        }
1259        Err(ErrorContext::new_missing(
1260            "Metrics",
1261            "Lock",
1262            self.orig_loc,
1263            self.buf.as_ptr() as usize,
1264        ))
1265    }
1266    pub fn get_mtu(&self) -> Result<u32, ErrorContext> {
1267        let mut iter = self.clone();
1268        iter.pos = 0;
1269        for attr in iter {
1270            if let Metrics::Mtu(val) = attr? {
1271                return Ok(val);
1272            }
1273        }
1274        Err(ErrorContext::new_missing(
1275            "Metrics",
1276            "Mtu",
1277            self.orig_loc,
1278            self.buf.as_ptr() as usize,
1279        ))
1280    }
1281    pub fn get_window(&self) -> Result<u32, ErrorContext> {
1282        let mut iter = self.clone();
1283        iter.pos = 0;
1284        for attr in iter {
1285            if let Metrics::Window(val) = attr? {
1286                return Ok(val);
1287            }
1288        }
1289        Err(ErrorContext::new_missing(
1290            "Metrics",
1291            "Window",
1292            self.orig_loc,
1293            self.buf.as_ptr() as usize,
1294        ))
1295    }
1296    pub fn get_rtt(&self) -> Result<u32, ErrorContext> {
1297        let mut iter = self.clone();
1298        iter.pos = 0;
1299        for attr in iter {
1300            if let Metrics::Rtt(val) = attr? {
1301                return Ok(val);
1302            }
1303        }
1304        Err(ErrorContext::new_missing(
1305            "Metrics",
1306            "Rtt",
1307            self.orig_loc,
1308            self.buf.as_ptr() as usize,
1309        ))
1310    }
1311    pub fn get_rttvar(&self) -> Result<u32, ErrorContext> {
1312        let mut iter = self.clone();
1313        iter.pos = 0;
1314        for attr in iter {
1315            if let Metrics::Rttvar(val) = attr? {
1316                return Ok(val);
1317            }
1318        }
1319        Err(ErrorContext::new_missing(
1320            "Metrics",
1321            "Rttvar",
1322            self.orig_loc,
1323            self.buf.as_ptr() as usize,
1324        ))
1325    }
1326    pub fn get_ssthresh(&self) -> Result<u32, ErrorContext> {
1327        let mut iter = self.clone();
1328        iter.pos = 0;
1329        for attr in iter {
1330            if let Metrics::Ssthresh(val) = attr? {
1331                return Ok(val);
1332            }
1333        }
1334        Err(ErrorContext::new_missing(
1335            "Metrics",
1336            "Ssthresh",
1337            self.orig_loc,
1338            self.buf.as_ptr() as usize,
1339        ))
1340    }
1341    pub fn get_cwnd(&self) -> Result<u32, ErrorContext> {
1342        let mut iter = self.clone();
1343        iter.pos = 0;
1344        for attr in iter {
1345            if let Metrics::Cwnd(val) = attr? {
1346                return Ok(val);
1347            }
1348        }
1349        Err(ErrorContext::new_missing(
1350            "Metrics",
1351            "Cwnd",
1352            self.orig_loc,
1353            self.buf.as_ptr() as usize,
1354        ))
1355    }
1356    pub fn get_advmss(&self) -> Result<u32, ErrorContext> {
1357        let mut iter = self.clone();
1358        iter.pos = 0;
1359        for attr in iter {
1360            if let Metrics::Advmss(val) = attr? {
1361                return Ok(val);
1362            }
1363        }
1364        Err(ErrorContext::new_missing(
1365            "Metrics",
1366            "Advmss",
1367            self.orig_loc,
1368            self.buf.as_ptr() as usize,
1369        ))
1370    }
1371    pub fn get_reordering(&self) -> Result<u32, ErrorContext> {
1372        let mut iter = self.clone();
1373        iter.pos = 0;
1374        for attr in iter {
1375            if let Metrics::Reordering(val) = attr? {
1376                return Ok(val);
1377            }
1378        }
1379        Err(ErrorContext::new_missing(
1380            "Metrics",
1381            "Reordering",
1382            self.orig_loc,
1383            self.buf.as_ptr() as usize,
1384        ))
1385    }
1386    pub fn get_hoplimit(&self) -> Result<u32, ErrorContext> {
1387        let mut iter = self.clone();
1388        iter.pos = 0;
1389        for attr in iter {
1390            if let Metrics::Hoplimit(val) = attr? {
1391                return Ok(val);
1392            }
1393        }
1394        Err(ErrorContext::new_missing(
1395            "Metrics",
1396            "Hoplimit",
1397            self.orig_loc,
1398            self.buf.as_ptr() as usize,
1399        ))
1400    }
1401    pub fn get_initcwnd(&self) -> Result<u32, ErrorContext> {
1402        let mut iter = self.clone();
1403        iter.pos = 0;
1404        for attr in iter {
1405            if let Metrics::Initcwnd(val) = attr? {
1406                return Ok(val);
1407            }
1408        }
1409        Err(ErrorContext::new_missing(
1410            "Metrics",
1411            "Initcwnd",
1412            self.orig_loc,
1413            self.buf.as_ptr() as usize,
1414        ))
1415    }
1416    pub fn get_features(&self) -> Result<u32, ErrorContext> {
1417        let mut iter = self.clone();
1418        iter.pos = 0;
1419        for attr in iter {
1420            if let Metrics::Features(val) = attr? {
1421                return Ok(val);
1422            }
1423        }
1424        Err(ErrorContext::new_missing(
1425            "Metrics",
1426            "Features",
1427            self.orig_loc,
1428            self.buf.as_ptr() as usize,
1429        ))
1430    }
1431    pub fn get_rto_min(&self) -> Result<u32, ErrorContext> {
1432        let mut iter = self.clone();
1433        iter.pos = 0;
1434        for attr in iter {
1435            if let Metrics::RtoMin(val) = attr? {
1436                return Ok(val);
1437            }
1438        }
1439        Err(ErrorContext::new_missing(
1440            "Metrics",
1441            "RtoMin",
1442            self.orig_loc,
1443            self.buf.as_ptr() as usize,
1444        ))
1445    }
1446    pub fn get_initrwnd(&self) -> Result<u32, ErrorContext> {
1447        let mut iter = self.clone();
1448        iter.pos = 0;
1449        for attr in iter {
1450            if let Metrics::Initrwnd(val) = attr? {
1451                return Ok(val);
1452            }
1453        }
1454        Err(ErrorContext::new_missing(
1455            "Metrics",
1456            "Initrwnd",
1457            self.orig_loc,
1458            self.buf.as_ptr() as usize,
1459        ))
1460    }
1461    pub fn get_quickack(&self) -> Result<u32, ErrorContext> {
1462        let mut iter = self.clone();
1463        iter.pos = 0;
1464        for attr in iter {
1465            if let Metrics::Quickack(val) = attr? {
1466                return Ok(val);
1467            }
1468        }
1469        Err(ErrorContext::new_missing(
1470            "Metrics",
1471            "Quickack",
1472            self.orig_loc,
1473            self.buf.as_ptr() as usize,
1474        ))
1475    }
1476    pub fn get_cc_algo(&self) -> Result<&'a CStr, ErrorContext> {
1477        let mut iter = self.clone();
1478        iter.pos = 0;
1479        for attr in iter {
1480            if let Metrics::CcAlgo(val) = attr? {
1481                return Ok(val);
1482            }
1483        }
1484        Err(ErrorContext::new_missing(
1485            "Metrics",
1486            "CcAlgo",
1487            self.orig_loc,
1488            self.buf.as_ptr() as usize,
1489        ))
1490    }
1491    pub fn get_fastopen_no_cookie(&self) -> Result<u32, ErrorContext> {
1492        let mut iter = self.clone();
1493        iter.pos = 0;
1494        for attr in iter {
1495            if let Metrics::FastopenNoCookie(val) = attr? {
1496                return Ok(val);
1497            }
1498        }
1499        Err(ErrorContext::new_missing(
1500            "Metrics",
1501            "FastopenNoCookie",
1502            self.orig_loc,
1503            self.buf.as_ptr() as usize,
1504        ))
1505    }
1506}
1507impl Metrics<'_> {
1508    pub fn new<'a>(buf: &'a [u8]) -> IterableMetrics<'a> {
1509        IterableMetrics::with_loc(buf, buf.as_ptr() as usize)
1510    }
1511    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1512        let res = match r#type {
1513            0u16 => "Unspec",
1514            1u16 => "Lock",
1515            2u16 => "Mtu",
1516            3u16 => "Window",
1517            4u16 => "Rtt",
1518            5u16 => "Rttvar",
1519            6u16 => "Ssthresh",
1520            7u16 => "Cwnd",
1521            8u16 => "Advmss",
1522            9u16 => "Reordering",
1523            10u16 => "Hoplimit",
1524            11u16 => "Initcwnd",
1525            12u16 => "Features",
1526            13u16 => "RtoMin",
1527            14u16 => "Initrwnd",
1528            15u16 => "Quickack",
1529            16u16 => "CcAlgo",
1530            17u16 => "FastopenNoCookie",
1531            _ => return None,
1532        };
1533        Some(res)
1534    }
1535}
1536#[derive(Clone, Copy, Default)]
1537pub struct IterableMetrics<'a> {
1538    buf: &'a [u8],
1539    pos: usize,
1540    orig_loc: usize,
1541}
1542impl<'a> IterableMetrics<'a> {
1543    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1544        Self {
1545            buf,
1546            pos: 0,
1547            orig_loc,
1548        }
1549    }
1550    pub fn get_buf(&self) -> &'a [u8] {
1551        self.buf
1552    }
1553}
1554impl<'a> Iterator for IterableMetrics<'a> {
1555    type Item = Result<Metrics<'a>, ErrorContext>;
1556    fn next(&mut self) -> Option<Self::Item> {
1557        let pos = self.pos;
1558        let mut r#type;
1559        loop {
1560            r#type = None;
1561            if self.buf.len() == self.pos {
1562                return None;
1563            }
1564            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1565                break;
1566            };
1567            r#type = Some(header.r#type);
1568            let res = match header.r#type {
1569                1u16 => Metrics::Lock({
1570                    let res = parse_u32(next);
1571                    let Some(val) = res else { break };
1572                    val
1573                }),
1574                2u16 => Metrics::Mtu({
1575                    let res = parse_u32(next);
1576                    let Some(val) = res else { break };
1577                    val
1578                }),
1579                3u16 => Metrics::Window({
1580                    let res = parse_u32(next);
1581                    let Some(val) = res else { break };
1582                    val
1583                }),
1584                4u16 => Metrics::Rtt({
1585                    let res = parse_u32(next);
1586                    let Some(val) = res else { break };
1587                    val
1588                }),
1589                5u16 => Metrics::Rttvar({
1590                    let res = parse_u32(next);
1591                    let Some(val) = res else { break };
1592                    val
1593                }),
1594                6u16 => Metrics::Ssthresh({
1595                    let res = parse_u32(next);
1596                    let Some(val) = res else { break };
1597                    val
1598                }),
1599                7u16 => Metrics::Cwnd({
1600                    let res = parse_u32(next);
1601                    let Some(val) = res else { break };
1602                    val
1603                }),
1604                8u16 => Metrics::Advmss({
1605                    let res = parse_u32(next);
1606                    let Some(val) = res else { break };
1607                    val
1608                }),
1609                9u16 => Metrics::Reordering({
1610                    let res = parse_u32(next);
1611                    let Some(val) = res else { break };
1612                    val
1613                }),
1614                10u16 => Metrics::Hoplimit({
1615                    let res = parse_u32(next);
1616                    let Some(val) = res else { break };
1617                    val
1618                }),
1619                11u16 => Metrics::Initcwnd({
1620                    let res = parse_u32(next);
1621                    let Some(val) = res else { break };
1622                    val
1623                }),
1624                12u16 => Metrics::Features({
1625                    let res = parse_u32(next);
1626                    let Some(val) = res else { break };
1627                    val
1628                }),
1629                13u16 => Metrics::RtoMin({
1630                    let res = parse_u32(next);
1631                    let Some(val) = res else { break };
1632                    val
1633                }),
1634                14u16 => Metrics::Initrwnd({
1635                    let res = parse_u32(next);
1636                    let Some(val) = res else { break };
1637                    val
1638                }),
1639                15u16 => Metrics::Quickack({
1640                    let res = parse_u32(next);
1641                    let Some(val) = res else { break };
1642                    val
1643                }),
1644                16u16 => Metrics::CcAlgo({
1645                    let res = CStr::from_bytes_with_nul(next).ok();
1646                    let Some(val) = res else { break };
1647                    val
1648                }),
1649                17u16 => Metrics::FastopenNoCookie({
1650                    let res = parse_u32(next);
1651                    let Some(val) = res else { break };
1652                    val
1653                }),
1654                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1655                n => continue,
1656            };
1657            return Some(Ok(res));
1658        }
1659        Some(Err(ErrorContext::new(
1660            "Metrics",
1661            r#type.and_then(|t| Metrics::attr_from_type(t)),
1662            self.orig_loc,
1663            self.buf.as_ptr().wrapping_add(pos) as usize,
1664        )))
1665    }
1666}
1667impl<'a> std::fmt::Debug for IterableMetrics<'_> {
1668    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1669        let mut fmt = f.debug_struct("Metrics");
1670        for attr in self.clone() {
1671            let attr = match attr {
1672                Ok(a) => a,
1673                Err(err) => {
1674                    fmt.finish()?;
1675                    f.write_str("Err(")?;
1676                    err.fmt(f)?;
1677                    return f.write_str(")");
1678                }
1679            };
1680            match attr {
1681                Metrics::Lock(val) => fmt.field("Lock", &val),
1682                Metrics::Mtu(val) => fmt.field("Mtu", &val),
1683                Metrics::Window(val) => fmt.field("Window", &val),
1684                Metrics::Rtt(val) => fmt.field("Rtt", &val),
1685                Metrics::Rttvar(val) => fmt.field("Rttvar", &val),
1686                Metrics::Ssthresh(val) => fmt.field("Ssthresh", &val),
1687                Metrics::Cwnd(val) => fmt.field("Cwnd", &val),
1688                Metrics::Advmss(val) => fmt.field("Advmss", &val),
1689                Metrics::Reordering(val) => fmt.field("Reordering", &val),
1690                Metrics::Hoplimit(val) => fmt.field("Hoplimit", &val),
1691                Metrics::Initcwnd(val) => fmt.field("Initcwnd", &val),
1692                Metrics::Features(val) => fmt.field("Features", &val),
1693                Metrics::RtoMin(val) => fmt.field("RtoMin", &val),
1694                Metrics::Initrwnd(val) => fmt.field("Initrwnd", &val),
1695                Metrics::Quickack(val) => fmt.field("Quickack", &val),
1696                Metrics::CcAlgo(val) => fmt.field("CcAlgo", &val),
1697                Metrics::FastopenNoCookie(val) => fmt.field("FastopenNoCookie", &val),
1698            };
1699        }
1700        fmt.finish()
1701    }
1702}
1703impl IterableMetrics<'_> {
1704    pub fn lookup_attr(
1705        &self,
1706        offset: usize,
1707        missing_type: Option<u16>,
1708    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1709        let mut stack = Vec::new();
1710        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1711        if missing_type.is_some() && cur == offset {
1712            stack.push(("Metrics", offset));
1713            return (stack, missing_type.and_then(|t| Metrics::attr_from_type(t)));
1714        }
1715        if cur > offset || cur + self.buf.len() < offset {
1716            return (stack, None);
1717        }
1718        let mut attrs = self.clone();
1719        let mut last_off = cur + attrs.pos;
1720        while let Some(attr) = attrs.next() {
1721            let Ok(attr) = attr else { break };
1722            match attr {
1723                Metrics::Lock(val) => {
1724                    if last_off == offset {
1725                        stack.push(("Lock", last_off));
1726                        break;
1727                    }
1728                }
1729                Metrics::Mtu(val) => {
1730                    if last_off == offset {
1731                        stack.push(("Mtu", last_off));
1732                        break;
1733                    }
1734                }
1735                Metrics::Window(val) => {
1736                    if last_off == offset {
1737                        stack.push(("Window", last_off));
1738                        break;
1739                    }
1740                }
1741                Metrics::Rtt(val) => {
1742                    if last_off == offset {
1743                        stack.push(("Rtt", last_off));
1744                        break;
1745                    }
1746                }
1747                Metrics::Rttvar(val) => {
1748                    if last_off == offset {
1749                        stack.push(("Rttvar", last_off));
1750                        break;
1751                    }
1752                }
1753                Metrics::Ssthresh(val) => {
1754                    if last_off == offset {
1755                        stack.push(("Ssthresh", last_off));
1756                        break;
1757                    }
1758                }
1759                Metrics::Cwnd(val) => {
1760                    if last_off == offset {
1761                        stack.push(("Cwnd", last_off));
1762                        break;
1763                    }
1764                }
1765                Metrics::Advmss(val) => {
1766                    if last_off == offset {
1767                        stack.push(("Advmss", last_off));
1768                        break;
1769                    }
1770                }
1771                Metrics::Reordering(val) => {
1772                    if last_off == offset {
1773                        stack.push(("Reordering", last_off));
1774                        break;
1775                    }
1776                }
1777                Metrics::Hoplimit(val) => {
1778                    if last_off == offset {
1779                        stack.push(("Hoplimit", last_off));
1780                        break;
1781                    }
1782                }
1783                Metrics::Initcwnd(val) => {
1784                    if last_off == offset {
1785                        stack.push(("Initcwnd", last_off));
1786                        break;
1787                    }
1788                }
1789                Metrics::Features(val) => {
1790                    if last_off == offset {
1791                        stack.push(("Features", last_off));
1792                        break;
1793                    }
1794                }
1795                Metrics::RtoMin(val) => {
1796                    if last_off == offset {
1797                        stack.push(("RtoMin", last_off));
1798                        break;
1799                    }
1800                }
1801                Metrics::Initrwnd(val) => {
1802                    if last_off == offset {
1803                        stack.push(("Initrwnd", last_off));
1804                        break;
1805                    }
1806                }
1807                Metrics::Quickack(val) => {
1808                    if last_off == offset {
1809                        stack.push(("Quickack", last_off));
1810                        break;
1811                    }
1812                }
1813                Metrics::CcAlgo(val) => {
1814                    if last_off == offset {
1815                        stack.push(("CcAlgo", last_off));
1816                        break;
1817                    }
1818                }
1819                Metrics::FastopenNoCookie(val) => {
1820                    if last_off == offset {
1821                        stack.push(("FastopenNoCookie", last_off));
1822                        break;
1823                    }
1824                }
1825                _ => {}
1826            };
1827            last_off = cur + attrs.pos;
1828        }
1829        if !stack.is_empty() {
1830            stack.push(("Metrics", cur));
1831        }
1832        (stack, None)
1833    }
1834}
1835pub struct PushRouteAttrs<Prev: Rec> {
1836    pub(crate) prev: Option<Prev>,
1837    pub(crate) header_offset: Option<usize>,
1838}
1839impl<Prev: Rec> Rec for PushRouteAttrs<Prev> {
1840    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1841        self.prev.as_mut().unwrap().as_rec_mut()
1842    }
1843    fn as_rec(&self) -> &Vec<u8> {
1844        self.prev.as_ref().unwrap().as_rec()
1845    }
1846}
1847impl<Prev: Rec> PushRouteAttrs<Prev> {
1848    pub fn new(prev: Prev) -> Self {
1849        Self {
1850            prev: Some(prev),
1851            header_offset: None,
1852        }
1853    }
1854    pub fn end_nested(mut self) -> Prev {
1855        let mut prev = self.prev.take().unwrap();
1856        if let Some(header_offset) = &self.header_offset {
1857            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1858        }
1859        prev
1860    }
1861    pub fn push_dst(mut self, value: std::net::IpAddr) -> Self {
1862        push_header(self.as_rec_mut(), 1u16, {
1863            match &value {
1864                IpAddr::V4(_) => 4,
1865                IpAddr::V6(_) => 16,
1866            }
1867        } as u16);
1868        encode_ip(self.as_rec_mut(), value);
1869        self
1870    }
1871    pub fn push_src(mut self, value: std::net::IpAddr) -> Self {
1872        push_header(self.as_rec_mut(), 2u16, {
1873            match &value {
1874                IpAddr::V4(_) => 4,
1875                IpAddr::V6(_) => 16,
1876            }
1877        } as u16);
1878        encode_ip(self.as_rec_mut(), value);
1879        self
1880    }
1881    pub fn push_iif(mut self, value: u32) -> Self {
1882        push_header(self.as_rec_mut(), 3u16, 4 as u16);
1883        self.as_rec_mut().extend(value.to_ne_bytes());
1884        self
1885    }
1886    pub fn push_oif(mut self, value: u32) -> Self {
1887        push_header(self.as_rec_mut(), 4u16, 4 as u16);
1888        self.as_rec_mut().extend(value.to_ne_bytes());
1889        self
1890    }
1891    pub fn push_gateway(mut self, value: std::net::IpAddr) -> Self {
1892        push_header(self.as_rec_mut(), 5u16, {
1893            match &value {
1894                IpAddr::V4(_) => 4,
1895                IpAddr::V6(_) => 16,
1896            }
1897        } as u16);
1898        encode_ip(self.as_rec_mut(), value);
1899        self
1900    }
1901    pub fn push_priority(mut self, value: u32) -> Self {
1902        push_header(self.as_rec_mut(), 6u16, 4 as u16);
1903        self.as_rec_mut().extend(value.to_ne_bytes());
1904        self
1905    }
1906    pub fn push_prefsrc(mut self, value: std::net::IpAddr) -> Self {
1907        push_header(self.as_rec_mut(), 7u16, {
1908            match &value {
1909                IpAddr::V4(_) => 4,
1910                IpAddr::V6(_) => 16,
1911            }
1912        } as u16);
1913        encode_ip(self.as_rec_mut(), value);
1914        self
1915    }
1916    pub fn nested_metrics(mut self) -> PushMetrics<Self> {
1917        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
1918        PushMetrics {
1919            prev: Some(self),
1920            header_offset: Some(header_offset),
1921        }
1922    }
1923    pub fn push_multipath(mut self, value: &[u8]) -> Self {
1924        push_header(self.as_rec_mut(), 9u16, value.len() as u16);
1925        self.as_rec_mut().extend(value);
1926        self
1927    }
1928    pub fn push_protoinfo(mut self, value: &[u8]) -> Self {
1929        push_header(self.as_rec_mut(), 10u16, value.len() as u16);
1930        self.as_rec_mut().extend(value);
1931        self
1932    }
1933    pub fn push_flow(mut self, value: u32) -> Self {
1934        push_header(self.as_rec_mut(), 11u16, 4 as u16);
1935        self.as_rec_mut().extend(value.to_ne_bytes());
1936        self
1937    }
1938    pub fn push_cacheinfo(mut self, value: RtaCacheinfo) -> Self {
1939        push_header(self.as_rec_mut(), 12u16, value.as_slice().len() as u16);
1940        self.as_rec_mut().extend(value.as_slice());
1941        self
1942    }
1943    pub fn push_session(mut self, value: &[u8]) -> Self {
1944        push_header(self.as_rec_mut(), 13u16, value.len() as u16);
1945        self.as_rec_mut().extend(value);
1946        self
1947    }
1948    pub fn push_mp_algo(mut self, value: &[u8]) -> Self {
1949        push_header(self.as_rec_mut(), 14u16, value.len() as u16);
1950        self.as_rec_mut().extend(value);
1951        self
1952    }
1953    pub fn push_table(mut self, value: u32) -> Self {
1954        push_header(self.as_rec_mut(), 15u16, 4 as u16);
1955        self.as_rec_mut().extend(value.to_ne_bytes());
1956        self
1957    }
1958    pub fn push_mark(mut self, value: u32) -> Self {
1959        push_header(self.as_rec_mut(), 16u16, 4 as u16);
1960        self.as_rec_mut().extend(value.to_ne_bytes());
1961        self
1962    }
1963    pub fn push_mfc_stats(mut self, value: &[u8]) -> Self {
1964        push_header(self.as_rec_mut(), 17u16, value.len() as u16);
1965        self.as_rec_mut().extend(value);
1966        self
1967    }
1968    pub fn push_via(mut self, value: &[u8]) -> Self {
1969        push_header(self.as_rec_mut(), 18u16, value.len() as u16);
1970        self.as_rec_mut().extend(value);
1971        self
1972    }
1973    pub fn push_newdst(mut self, value: &[u8]) -> Self {
1974        push_header(self.as_rec_mut(), 19u16, value.len() as u16);
1975        self.as_rec_mut().extend(value);
1976        self
1977    }
1978    pub fn push_pref(mut self, value: u8) -> Self {
1979        push_header(self.as_rec_mut(), 20u16, 1 as u16);
1980        self.as_rec_mut().extend(value.to_ne_bytes());
1981        self
1982    }
1983    pub fn push_encap_type(mut self, value: u16) -> Self {
1984        push_header(self.as_rec_mut(), 21u16, 2 as u16);
1985        self.as_rec_mut().extend(value.to_ne_bytes());
1986        self
1987    }
1988    pub fn push_encap(mut self, value: &[u8]) -> Self {
1989        push_header(self.as_rec_mut(), 22u16, value.len() as u16);
1990        self.as_rec_mut().extend(value);
1991        self
1992    }
1993    pub fn push_expires(mut self, value: u32) -> Self {
1994        push_header(self.as_rec_mut(), 23u16, 4 as u16);
1995        self.as_rec_mut().extend(value.to_ne_bytes());
1996        self
1997    }
1998    pub fn push_pad(mut self, value: &[u8]) -> Self {
1999        push_header(self.as_rec_mut(), 24u16, value.len() as u16);
2000        self.as_rec_mut().extend(value);
2001        self
2002    }
2003    pub fn push_uid(mut self, value: u32) -> Self {
2004        push_header(self.as_rec_mut(), 25u16, 4 as u16);
2005        self.as_rec_mut().extend(value.to_ne_bytes());
2006        self
2007    }
2008    pub fn push_ttl_propagate(mut self, value: u8) -> Self {
2009        push_header(self.as_rec_mut(), 26u16, 1 as u16);
2010        self.as_rec_mut().extend(value.to_ne_bytes());
2011        self
2012    }
2013    pub fn push_ip_proto(mut self, value: u8) -> Self {
2014        push_header(self.as_rec_mut(), 27u16, 1 as u16);
2015        self.as_rec_mut().extend(value.to_ne_bytes());
2016        self
2017    }
2018    pub fn push_sport(mut self, value: u16) -> Self {
2019        push_header(self.as_rec_mut(), 28u16, 2 as u16);
2020        self.as_rec_mut().extend(value.to_ne_bytes());
2021        self
2022    }
2023    pub fn push_dport(mut self, value: u16) -> Self {
2024        push_header(self.as_rec_mut(), 29u16, 2 as u16);
2025        self.as_rec_mut().extend(value.to_ne_bytes());
2026        self
2027    }
2028    pub fn push_nh_id(mut self, value: u32) -> Self {
2029        push_header(self.as_rec_mut(), 30u16, 4 as u16);
2030        self.as_rec_mut().extend(value.to_ne_bytes());
2031        self
2032    }
2033    pub fn push_flowlabel(mut self, value: u32) -> Self {
2034        push_header(self.as_rec_mut(), 31u16, 4 as u16);
2035        self.as_rec_mut().extend(value.to_be_bytes());
2036        self
2037    }
2038}
2039impl<Prev: Rec> Drop for PushRouteAttrs<Prev> {
2040    fn drop(&mut self) {
2041        if let Some(prev) = &mut self.prev {
2042            if let Some(header_offset) = &self.header_offset {
2043                finalize_nested_header(prev.as_rec_mut(), *header_offset);
2044            }
2045        }
2046    }
2047}
2048pub struct PushMetrics<Prev: Rec> {
2049    pub(crate) prev: Option<Prev>,
2050    pub(crate) header_offset: Option<usize>,
2051}
2052impl<Prev: Rec> Rec for PushMetrics<Prev> {
2053    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2054        self.prev.as_mut().unwrap().as_rec_mut()
2055    }
2056    fn as_rec(&self) -> &Vec<u8> {
2057        self.prev.as_ref().unwrap().as_rec()
2058    }
2059}
2060impl<Prev: Rec> PushMetrics<Prev> {
2061    pub fn new(prev: Prev) -> Self {
2062        Self {
2063            prev: Some(prev),
2064            header_offset: None,
2065        }
2066    }
2067    pub fn end_nested(mut self) -> Prev {
2068        let mut prev = self.prev.take().unwrap();
2069        if let Some(header_offset) = &self.header_offset {
2070            finalize_nested_header(prev.as_rec_mut(), *header_offset);
2071        }
2072        prev
2073    }
2074    pub fn push_lock(mut self, value: u32) -> Self {
2075        push_header(self.as_rec_mut(), 1u16, 4 as u16);
2076        self.as_rec_mut().extend(value.to_ne_bytes());
2077        self
2078    }
2079    pub fn push_mtu(mut self, value: u32) -> Self {
2080        push_header(self.as_rec_mut(), 2u16, 4 as u16);
2081        self.as_rec_mut().extend(value.to_ne_bytes());
2082        self
2083    }
2084    pub fn push_window(mut self, value: u32) -> Self {
2085        push_header(self.as_rec_mut(), 3u16, 4 as u16);
2086        self.as_rec_mut().extend(value.to_ne_bytes());
2087        self
2088    }
2089    pub fn push_rtt(mut self, value: u32) -> Self {
2090        push_header(self.as_rec_mut(), 4u16, 4 as u16);
2091        self.as_rec_mut().extend(value.to_ne_bytes());
2092        self
2093    }
2094    pub fn push_rttvar(mut self, value: u32) -> Self {
2095        push_header(self.as_rec_mut(), 5u16, 4 as u16);
2096        self.as_rec_mut().extend(value.to_ne_bytes());
2097        self
2098    }
2099    pub fn push_ssthresh(mut self, value: u32) -> Self {
2100        push_header(self.as_rec_mut(), 6u16, 4 as u16);
2101        self.as_rec_mut().extend(value.to_ne_bytes());
2102        self
2103    }
2104    pub fn push_cwnd(mut self, value: u32) -> Self {
2105        push_header(self.as_rec_mut(), 7u16, 4 as u16);
2106        self.as_rec_mut().extend(value.to_ne_bytes());
2107        self
2108    }
2109    pub fn push_advmss(mut self, value: u32) -> Self {
2110        push_header(self.as_rec_mut(), 8u16, 4 as u16);
2111        self.as_rec_mut().extend(value.to_ne_bytes());
2112        self
2113    }
2114    pub fn push_reordering(mut self, value: u32) -> Self {
2115        push_header(self.as_rec_mut(), 9u16, 4 as u16);
2116        self.as_rec_mut().extend(value.to_ne_bytes());
2117        self
2118    }
2119    pub fn push_hoplimit(mut self, value: u32) -> Self {
2120        push_header(self.as_rec_mut(), 10u16, 4 as u16);
2121        self.as_rec_mut().extend(value.to_ne_bytes());
2122        self
2123    }
2124    pub fn push_initcwnd(mut self, value: u32) -> Self {
2125        push_header(self.as_rec_mut(), 11u16, 4 as u16);
2126        self.as_rec_mut().extend(value.to_ne_bytes());
2127        self
2128    }
2129    pub fn push_features(mut self, value: u32) -> Self {
2130        push_header(self.as_rec_mut(), 12u16, 4 as u16);
2131        self.as_rec_mut().extend(value.to_ne_bytes());
2132        self
2133    }
2134    pub fn push_rto_min(mut self, value: u32) -> Self {
2135        push_header(self.as_rec_mut(), 13u16, 4 as u16);
2136        self.as_rec_mut().extend(value.to_ne_bytes());
2137        self
2138    }
2139    pub fn push_initrwnd(mut self, value: u32) -> Self {
2140        push_header(self.as_rec_mut(), 14u16, 4 as u16);
2141        self.as_rec_mut().extend(value.to_ne_bytes());
2142        self
2143    }
2144    pub fn push_quickack(mut self, value: u32) -> Self {
2145        push_header(self.as_rec_mut(), 15u16, 4 as u16);
2146        self.as_rec_mut().extend(value.to_ne_bytes());
2147        self
2148    }
2149    pub fn push_cc_algo(mut self, value: &CStr) -> Self {
2150        push_header(
2151            self.as_rec_mut(),
2152            16u16,
2153            value.to_bytes_with_nul().len() as u16,
2154        );
2155        self.as_rec_mut().extend(value.to_bytes_with_nul());
2156        self
2157    }
2158    pub fn push_cc_algo_bytes(mut self, value: &[u8]) -> Self {
2159        push_header(self.as_rec_mut(), 16u16, (value.len() + 1) as u16);
2160        self.as_rec_mut().extend(value);
2161        self.as_rec_mut().push(0);
2162        self
2163    }
2164    pub fn push_fastopen_no_cookie(mut self, value: u32) -> Self {
2165        push_header(self.as_rec_mut(), 17u16, 4 as u16);
2166        self.as_rec_mut().extend(value.to_ne_bytes());
2167        self
2168    }
2169}
2170impl<Prev: Rec> Drop for PushMetrics<Prev> {
2171    fn drop(&mut self) {
2172        if let Some(prev) = &mut self.prev {
2173            if let Some(header_offset) = &self.header_offset {
2174                finalize_nested_header(prev.as_rec_mut(), *header_offset);
2175            }
2176        }
2177    }
2178}
2179#[doc = "Dump route information\\.\n\nReply attributes:\n- [.get_dst()](IterableRouteAttrs::get_dst)\n- [.get_src()](IterableRouteAttrs::get_src)\n- [.get_iif()](IterableRouteAttrs::get_iif)\n- [.get_oif()](IterableRouteAttrs::get_oif)\n- [.get_gateway()](IterableRouteAttrs::get_gateway)\n- [.get_priority()](IterableRouteAttrs::get_priority)\n- [.get_prefsrc()](IterableRouteAttrs::get_prefsrc)\n- [.get_metrics()](IterableRouteAttrs::get_metrics)\n- [.get_multipath()](IterableRouteAttrs::get_multipath)\n- [.get_flow()](IterableRouteAttrs::get_flow)\n- [.get_cacheinfo()](IterableRouteAttrs::get_cacheinfo)\n- [.get_table()](IterableRouteAttrs::get_table)\n- [.get_mark()](IterableRouteAttrs::get_mark)\n- [.get_mfc_stats()](IterableRouteAttrs::get_mfc_stats)\n- [.get_via()](IterableRouteAttrs::get_via)\n- [.get_newdst()](IterableRouteAttrs::get_newdst)\n- [.get_pref()](IterableRouteAttrs::get_pref)\n- [.get_encap_type()](IterableRouteAttrs::get_encap_type)\n- [.get_encap()](IterableRouteAttrs::get_encap)\n- [.get_expires()](IterableRouteAttrs::get_expires)\n- [.get_pad()](IterableRouteAttrs::get_pad)\n- [.get_uid()](IterableRouteAttrs::get_uid)\n- [.get_ttl_propagate()](IterableRouteAttrs::get_ttl_propagate)\n- [.get_ip_proto()](IterableRouteAttrs::get_ip_proto)\n- [.get_sport()](IterableRouteAttrs::get_sport)\n- [.get_dport()](IterableRouteAttrs::get_dport)\n- [.get_nh_id()](IterableRouteAttrs::get_nh_id)\n- [.get_flowlabel()](IterableRouteAttrs::get_flowlabel)\n"]
2180#[derive(Debug)]
2181pub struct OpGetrouteDump<'r> {
2182    request: Request<'r>,
2183}
2184impl<'r> OpGetrouteDump<'r> {
2185    pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2186        Self::write_header(request.buf_mut(), header);
2187        Self {
2188            request: request.set_dump(),
2189        }
2190    }
2191    pub fn encode_request<'buf>(
2192        buf: &'buf mut Vec<u8>,
2193        header: &Rtmsg,
2194    ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2195        Self::write_header(buf, header);
2196        PushRouteAttrs::new(buf)
2197    }
2198    pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2199        PushRouteAttrs::new(self.request.buf_mut())
2200    }
2201    pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2202        PushRouteAttrs::new(self.request.buf)
2203    }
2204    pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2205        let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2206        (
2207            Rtmsg::new_from_slice(header).unwrap_or_default(),
2208            IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2209        )
2210    }
2211    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2212        prev.as_rec_mut().extend(header.as_slice());
2213    }
2214}
2215impl NetlinkRequest for OpGetrouteDump<'_> {
2216    fn protocol(&self) -> Protocol {
2217        Protocol::Raw {
2218            protonum: 0u16,
2219            request_type: 26u16,
2220        }
2221    }
2222    fn flags(&self) -> u16 {
2223        self.request.flags
2224    }
2225    fn payload(&self) -> &[u8] {
2226        self.request.buf()
2227    }
2228    type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2229    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2230        Self::decode_request(buf)
2231    }
2232    fn lookup(
2233        buf: &[u8],
2234        offset: usize,
2235        missing_type: Option<u16>,
2236    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2237        Self::decode_request(buf)
2238            .1
2239            .lookup_attr(offset, missing_type)
2240    }
2241}
2242#[doc = "Dump route information\\.\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n\nReply attributes:\n- [.get_dst()](IterableRouteAttrs::get_dst)\n- [.get_src()](IterableRouteAttrs::get_src)\n- [.get_iif()](IterableRouteAttrs::get_iif)\n- [.get_oif()](IterableRouteAttrs::get_oif)\n- [.get_gateway()](IterableRouteAttrs::get_gateway)\n- [.get_priority()](IterableRouteAttrs::get_priority)\n- [.get_prefsrc()](IterableRouteAttrs::get_prefsrc)\n- [.get_metrics()](IterableRouteAttrs::get_metrics)\n- [.get_multipath()](IterableRouteAttrs::get_multipath)\n- [.get_flow()](IterableRouteAttrs::get_flow)\n- [.get_cacheinfo()](IterableRouteAttrs::get_cacheinfo)\n- [.get_table()](IterableRouteAttrs::get_table)\n- [.get_mark()](IterableRouteAttrs::get_mark)\n- [.get_mfc_stats()](IterableRouteAttrs::get_mfc_stats)\n- [.get_via()](IterableRouteAttrs::get_via)\n- [.get_newdst()](IterableRouteAttrs::get_newdst)\n- [.get_pref()](IterableRouteAttrs::get_pref)\n- [.get_encap_type()](IterableRouteAttrs::get_encap_type)\n- [.get_encap()](IterableRouteAttrs::get_encap)\n- [.get_expires()](IterableRouteAttrs::get_expires)\n- [.get_pad()](IterableRouteAttrs::get_pad)\n- [.get_uid()](IterableRouteAttrs::get_uid)\n- [.get_ttl_propagate()](IterableRouteAttrs::get_ttl_propagate)\n- [.get_ip_proto()](IterableRouteAttrs::get_ip_proto)\n- [.get_sport()](IterableRouteAttrs::get_sport)\n- [.get_dport()](IterableRouteAttrs::get_dport)\n- [.get_nh_id()](IterableRouteAttrs::get_nh_id)\n- [.get_flowlabel()](IterableRouteAttrs::get_flowlabel)\n"]
2243#[derive(Debug)]
2244pub struct OpGetrouteDo<'r> {
2245    request: Request<'r>,
2246}
2247impl<'r> OpGetrouteDo<'r> {
2248    pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2249        Self::write_header(request.buf_mut(), header);
2250        Self { request: request }
2251    }
2252    pub fn encode_request<'buf>(
2253        buf: &'buf mut Vec<u8>,
2254        header: &Rtmsg,
2255    ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2256        Self::write_header(buf, header);
2257        PushRouteAttrs::new(buf)
2258    }
2259    pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2260        PushRouteAttrs::new(self.request.buf_mut())
2261    }
2262    pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2263        PushRouteAttrs::new(self.request.buf)
2264    }
2265    pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2266        let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2267        (
2268            Rtmsg::new_from_slice(header).unwrap_or_default(),
2269            IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2270        )
2271    }
2272    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2273        prev.as_rec_mut().extend(header.as_slice());
2274    }
2275}
2276impl NetlinkRequest for OpGetrouteDo<'_> {
2277    fn protocol(&self) -> Protocol {
2278        Protocol::Raw {
2279            protonum: 0u16,
2280            request_type: 26u16,
2281        }
2282    }
2283    fn flags(&self) -> u16 {
2284        self.request.flags
2285    }
2286    fn payload(&self) -> &[u8] {
2287        self.request.buf()
2288    }
2289    type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2290    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2291        Self::decode_request(buf)
2292    }
2293    fn lookup(
2294        buf: &[u8],
2295        offset: usize,
2296        missing_type: Option<u16>,
2297    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2298        Self::decode_request(buf)
2299            .1
2300            .lookup_attr(offset, missing_type)
2301    }
2302}
2303#[doc = "Create a new route\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_gateway()](PushRouteAttrs::push_gateway)\n- [.push_priority()](PushRouteAttrs::push_priority)\n- [.push_prefsrc()](PushRouteAttrs::push_prefsrc)\n- [.nested_metrics()](PushRouteAttrs::nested_metrics)\n- [.push_multipath()](PushRouteAttrs::push_multipath)\n- [.push_flow()](PushRouteAttrs::push_flow)\n- [.push_cacheinfo()](PushRouteAttrs::push_cacheinfo)\n- [.push_table()](PushRouteAttrs::push_table)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_mfc_stats()](PushRouteAttrs::push_mfc_stats)\n- [.push_via()](PushRouteAttrs::push_via)\n- [.push_newdst()](PushRouteAttrs::push_newdst)\n- [.push_pref()](PushRouteAttrs::push_pref)\n- [.push_encap_type()](PushRouteAttrs::push_encap_type)\n- [.push_encap()](PushRouteAttrs::push_encap)\n- [.push_expires()](PushRouteAttrs::push_expires)\n- [.push_pad()](PushRouteAttrs::push_pad)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ttl_propagate()](PushRouteAttrs::push_ttl_propagate)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_nh_id()](PushRouteAttrs::push_nh_id)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n"]
2304#[derive(Debug)]
2305pub struct OpNewrouteDo<'r> {
2306    request: Request<'r>,
2307}
2308impl<'r> OpNewrouteDo<'r> {
2309    pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2310        Self::write_header(request.buf_mut(), header);
2311        Self { request: request }
2312    }
2313    pub fn encode_request<'buf>(
2314        buf: &'buf mut Vec<u8>,
2315        header: &Rtmsg,
2316    ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2317        Self::write_header(buf, header);
2318        PushRouteAttrs::new(buf)
2319    }
2320    pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2321        PushRouteAttrs::new(self.request.buf_mut())
2322    }
2323    pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2324        PushRouteAttrs::new(self.request.buf)
2325    }
2326    pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2327        let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2328        (
2329            Rtmsg::new_from_slice(header).unwrap_or_default(),
2330            IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2331        )
2332    }
2333    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2334        prev.as_rec_mut().extend(header.as_slice());
2335    }
2336}
2337impl NetlinkRequest for OpNewrouteDo<'_> {
2338    fn protocol(&self) -> Protocol {
2339        Protocol::Raw {
2340            protonum: 0u16,
2341            request_type: 24u16,
2342        }
2343    }
2344    fn flags(&self) -> u16 {
2345        self.request.flags
2346    }
2347    fn payload(&self) -> &[u8] {
2348        self.request.buf()
2349    }
2350    type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2351    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2352        Self::decode_request(buf)
2353    }
2354    fn lookup(
2355        buf: &[u8],
2356        offset: usize,
2357        missing_type: Option<u16>,
2358    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2359        Self::decode_request(buf)
2360            .1
2361            .lookup_attr(offset, missing_type)
2362    }
2363}
2364#[doc = "Delete an existing route\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_gateway()](PushRouteAttrs::push_gateway)\n- [.push_priority()](PushRouteAttrs::push_priority)\n- [.push_prefsrc()](PushRouteAttrs::push_prefsrc)\n- [.nested_metrics()](PushRouteAttrs::nested_metrics)\n- [.push_multipath()](PushRouteAttrs::push_multipath)\n- [.push_flow()](PushRouteAttrs::push_flow)\n- [.push_cacheinfo()](PushRouteAttrs::push_cacheinfo)\n- [.push_table()](PushRouteAttrs::push_table)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_mfc_stats()](PushRouteAttrs::push_mfc_stats)\n- [.push_via()](PushRouteAttrs::push_via)\n- [.push_newdst()](PushRouteAttrs::push_newdst)\n- [.push_pref()](PushRouteAttrs::push_pref)\n- [.push_encap_type()](PushRouteAttrs::push_encap_type)\n- [.push_encap()](PushRouteAttrs::push_encap)\n- [.push_expires()](PushRouteAttrs::push_expires)\n- [.push_pad()](PushRouteAttrs::push_pad)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ttl_propagate()](PushRouteAttrs::push_ttl_propagate)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_nh_id()](PushRouteAttrs::push_nh_id)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n"]
2365#[derive(Debug)]
2366pub struct OpDelrouteDo<'r> {
2367    request: Request<'r>,
2368}
2369impl<'r> OpDelrouteDo<'r> {
2370    pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2371        Self::write_header(request.buf_mut(), header);
2372        Self { request: request }
2373    }
2374    pub fn encode_request<'buf>(
2375        buf: &'buf mut Vec<u8>,
2376        header: &Rtmsg,
2377    ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2378        Self::write_header(buf, header);
2379        PushRouteAttrs::new(buf)
2380    }
2381    pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2382        PushRouteAttrs::new(self.request.buf_mut())
2383    }
2384    pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2385        PushRouteAttrs::new(self.request.buf)
2386    }
2387    pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2388        let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2389        (
2390            Rtmsg::new_from_slice(header).unwrap_or_default(),
2391            IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2392        )
2393    }
2394    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2395        prev.as_rec_mut().extend(header.as_slice());
2396    }
2397}
2398impl NetlinkRequest for OpDelrouteDo<'_> {
2399    fn protocol(&self) -> Protocol {
2400        Protocol::Raw {
2401            protonum: 0u16,
2402            request_type: 25u16,
2403        }
2404    }
2405    fn flags(&self) -> u16 {
2406        self.request.flags
2407    }
2408    fn payload(&self) -> &[u8] {
2409        self.request.buf()
2410    }
2411    type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2412    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2413        Self::decode_request(buf)
2414    }
2415    fn lookup(
2416        buf: &[u8],
2417        offset: usize,
2418        missing_type: Option<u16>,
2419    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2420        Self::decode_request(buf)
2421            .1
2422            .lookup_attr(offset, missing_type)
2423    }
2424}
2425#[derive(Debug)]
2426pub struct ChainedFinal<'a> {
2427    inner: Chained<'a>,
2428}
2429#[derive(Debug)]
2430pub struct Chained<'a> {
2431    buf: RequestBuf<'a>,
2432    first_seq: u32,
2433    lookups: Vec<(&'static str, LookupFn)>,
2434    last_header_offset: usize,
2435    last_kind: Option<RequestInfo>,
2436}
2437impl<'a> ChainedFinal<'a> {
2438    pub fn into_chained(self) -> Chained<'a> {
2439        self.inner
2440    }
2441    pub fn buf(&self) -> &Vec<u8> {
2442        self.inner.buf()
2443    }
2444    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2445        self.inner.buf_mut()
2446    }
2447    fn get_index(&self, seq: u32) -> Option<u32> {
2448        let min = self.inner.first_seq;
2449        let max = min.wrapping_add(self.inner.lookups.len() as u32);
2450        return if min <= max {
2451            (min..max).contains(&seq).then(|| seq - min)
2452        } else if min <= seq {
2453            Some(seq - min)
2454        } else if seq < max {
2455            Some(u32::MAX - min + seq)
2456        } else {
2457            None
2458        };
2459    }
2460}
2461impl crate::traits::NetlinkChained for ChainedFinal<'_> {
2462    fn protonum(&self) -> u16 {
2463        PROTONUM
2464    }
2465    fn payload(&self) -> &[u8] {
2466        self.buf()
2467    }
2468    fn chain_len(&self) -> usize {
2469        self.inner.lookups.len()
2470    }
2471    fn get_index(&self, seq: u32) -> Option<usize> {
2472        self.get_index(seq).map(|n| n as usize)
2473    }
2474    fn name(&self, index: usize) -> &'static str {
2475        self.inner.lookups[index].0
2476    }
2477    fn lookup(&self, index: usize) -> LookupFn {
2478        self.inner.lookups[index].1
2479    }
2480}
2481impl Chained<'static> {
2482    pub fn new(first_seq: u32) -> Self {
2483        Self::new_from_buf(Vec::new(), first_seq)
2484    }
2485    pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
2486        Self {
2487            buf: RequestBuf::Own(buf),
2488            first_seq,
2489            lookups: Vec::new(),
2490            last_header_offset: 0,
2491            last_kind: None,
2492        }
2493    }
2494    pub fn into_buf(self) -> Vec<u8> {
2495        match self.buf {
2496            RequestBuf::Own(buf) => buf,
2497            _ => unreachable!(),
2498        }
2499    }
2500}
2501impl<'a> Chained<'a> {
2502    pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
2503        Self {
2504            buf: RequestBuf::Ref(buf),
2505            first_seq,
2506            lookups: Vec::new(),
2507            last_header_offset: 0,
2508            last_kind: None,
2509        }
2510    }
2511    pub fn finalize(mut self) -> ChainedFinal<'a> {
2512        self.update_header();
2513        ChainedFinal { inner: self }
2514    }
2515    pub fn request(&mut self) -> Request<'_> {
2516        self.update_header();
2517        self.last_header_offset = self.buf().len();
2518        self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
2519        let mut request = Request::new_extend(self.buf.buf_mut());
2520        self.last_kind = None;
2521        request.writeback = Some(&mut self.last_kind);
2522        request
2523    }
2524    pub fn buf(&self) -> &Vec<u8> {
2525        self.buf.buf()
2526    }
2527    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2528        self.buf.buf_mut()
2529    }
2530    fn update_header(&mut self) {
2531        let Some(RequestInfo {
2532            protocol,
2533            flags,
2534            name,
2535            lookup,
2536        }) = self.last_kind
2537        else {
2538            if !self.buf().is_empty() {
2539                assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
2540                self.buf.buf_mut().truncate(self.last_header_offset);
2541            }
2542            return;
2543        };
2544        let header_offset = self.last_header_offset;
2545        let request_type = match protocol {
2546            Protocol::Raw { request_type, .. } => request_type,
2547            Protocol::Generic(_) => unreachable!(),
2548        };
2549        let index = self.lookups.len();
2550        let seq = self.first_seq.wrapping_add(index as u32);
2551        self.lookups.push((name, lookup));
2552        let buf = self.buf_mut();
2553        align(buf);
2554        let header = Nlmsghdr {
2555            len: (buf.len() - header_offset) as u32,
2556            r#type: request_type,
2557            flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
2558            seq,
2559            pid: 0,
2560        };
2561        buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
2562    }
2563}
2564use crate::traits::LookupFn;
2565use crate::utils::RequestBuf;
2566#[derive(Debug)]
2567pub struct Request<'buf> {
2568    buf: RequestBuf<'buf>,
2569    flags: u16,
2570    writeback: Option<&'buf mut Option<RequestInfo>>,
2571}
2572#[allow(unused)]
2573#[derive(Debug, Clone)]
2574pub struct RequestInfo {
2575    protocol: Protocol,
2576    flags: u16,
2577    name: &'static str,
2578    lookup: LookupFn,
2579}
2580impl Request<'static> {
2581    pub fn new() -> Self {
2582        Self::new_from_buf(Vec::new())
2583    }
2584    pub fn new_from_buf(buf: Vec<u8>) -> Self {
2585        Self {
2586            flags: 0,
2587            buf: RequestBuf::Own(buf),
2588            writeback: None,
2589        }
2590    }
2591    pub fn into_buf(self) -> Vec<u8> {
2592        match self.buf {
2593            RequestBuf::Own(buf) => buf,
2594            _ => unreachable!(),
2595        }
2596    }
2597}
2598impl<'buf> Request<'buf> {
2599    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
2600        buf.clear();
2601        Self::new_extend(buf)
2602    }
2603    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
2604        Self {
2605            flags: 0,
2606            buf: RequestBuf::Ref(buf),
2607            writeback: None,
2608        }
2609    }
2610    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
2611        let Some(writeback) = &mut self.writeback else {
2612            return;
2613        };
2614        **writeback = Some(RequestInfo {
2615            protocol,
2616            flags: self.flags,
2617            name,
2618            lookup,
2619        })
2620    }
2621    pub fn buf(&self) -> &Vec<u8> {
2622        self.buf.buf()
2623    }
2624    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2625        self.buf.buf_mut()
2626    }
2627    #[doc = "Set `NLM_F_CREATE` flag"]
2628    pub fn set_create(mut self) -> Self {
2629        self.flags |= consts::NLM_F_CREATE as u16;
2630        self
2631    }
2632    #[doc = "Set `NLM_F_EXCL` flag"]
2633    pub fn set_excl(mut self) -> Self {
2634        self.flags |= consts::NLM_F_EXCL as u16;
2635        self
2636    }
2637    #[doc = "Set `NLM_F_REPLACE` flag"]
2638    pub fn set_replace(mut self) -> Self {
2639        self.flags |= consts::NLM_F_REPLACE as u16;
2640        self
2641    }
2642    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
2643    pub fn set_change(self) -> Self {
2644        self.set_create().set_replace()
2645    }
2646    #[doc = "Set `NLM_F_APPEND` flag"]
2647    pub fn set_append(mut self) -> Self {
2648        self.flags |= consts::NLM_F_APPEND as u16;
2649        self
2650    }
2651    #[doc = "Set `self.flags |= flags`"]
2652    pub fn set_flags(mut self, flags: u16) -> Self {
2653        self.flags |= flags;
2654        self
2655    }
2656    #[doc = "Set `self.flags ^= self.flags & flags`"]
2657    pub fn unset_flags(mut self, flags: u16) -> Self {
2658        self.flags ^= self.flags & flags;
2659        self
2660    }
2661    #[doc = "Set `NLM_F_DUMP` flag"]
2662    fn set_dump(mut self) -> Self {
2663        self.flags |= consts::NLM_F_DUMP as u16;
2664        self
2665    }
2666    #[doc = "Dump route information\\.\n\nReply attributes:\n- [.get_dst()](IterableRouteAttrs::get_dst)\n- [.get_src()](IterableRouteAttrs::get_src)\n- [.get_iif()](IterableRouteAttrs::get_iif)\n- [.get_oif()](IterableRouteAttrs::get_oif)\n- [.get_gateway()](IterableRouteAttrs::get_gateway)\n- [.get_priority()](IterableRouteAttrs::get_priority)\n- [.get_prefsrc()](IterableRouteAttrs::get_prefsrc)\n- [.get_metrics()](IterableRouteAttrs::get_metrics)\n- [.get_multipath()](IterableRouteAttrs::get_multipath)\n- [.get_flow()](IterableRouteAttrs::get_flow)\n- [.get_cacheinfo()](IterableRouteAttrs::get_cacheinfo)\n- [.get_table()](IterableRouteAttrs::get_table)\n- [.get_mark()](IterableRouteAttrs::get_mark)\n- [.get_mfc_stats()](IterableRouteAttrs::get_mfc_stats)\n- [.get_via()](IterableRouteAttrs::get_via)\n- [.get_newdst()](IterableRouteAttrs::get_newdst)\n- [.get_pref()](IterableRouteAttrs::get_pref)\n- [.get_encap_type()](IterableRouteAttrs::get_encap_type)\n- [.get_encap()](IterableRouteAttrs::get_encap)\n- [.get_expires()](IterableRouteAttrs::get_expires)\n- [.get_pad()](IterableRouteAttrs::get_pad)\n- [.get_uid()](IterableRouteAttrs::get_uid)\n- [.get_ttl_propagate()](IterableRouteAttrs::get_ttl_propagate)\n- [.get_ip_proto()](IterableRouteAttrs::get_ip_proto)\n- [.get_sport()](IterableRouteAttrs::get_sport)\n- [.get_dport()](IterableRouteAttrs::get_dport)\n- [.get_nh_id()](IterableRouteAttrs::get_nh_id)\n- [.get_flowlabel()](IterableRouteAttrs::get_flowlabel)\n"]
2667    pub fn op_getroute_dump(self, header: &Rtmsg) -> OpGetrouteDump<'buf> {
2668        let mut res = OpGetrouteDump::new(self, header);
2669        res.request
2670            .do_writeback(res.protocol(), "op-getroute-dump", OpGetrouteDump::lookup);
2671        res
2672    }
2673    #[doc = "Dump route information\\.\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n\nReply attributes:\n- [.get_dst()](IterableRouteAttrs::get_dst)\n- [.get_src()](IterableRouteAttrs::get_src)\n- [.get_iif()](IterableRouteAttrs::get_iif)\n- [.get_oif()](IterableRouteAttrs::get_oif)\n- [.get_gateway()](IterableRouteAttrs::get_gateway)\n- [.get_priority()](IterableRouteAttrs::get_priority)\n- [.get_prefsrc()](IterableRouteAttrs::get_prefsrc)\n- [.get_metrics()](IterableRouteAttrs::get_metrics)\n- [.get_multipath()](IterableRouteAttrs::get_multipath)\n- [.get_flow()](IterableRouteAttrs::get_flow)\n- [.get_cacheinfo()](IterableRouteAttrs::get_cacheinfo)\n- [.get_table()](IterableRouteAttrs::get_table)\n- [.get_mark()](IterableRouteAttrs::get_mark)\n- [.get_mfc_stats()](IterableRouteAttrs::get_mfc_stats)\n- [.get_via()](IterableRouteAttrs::get_via)\n- [.get_newdst()](IterableRouteAttrs::get_newdst)\n- [.get_pref()](IterableRouteAttrs::get_pref)\n- [.get_encap_type()](IterableRouteAttrs::get_encap_type)\n- [.get_encap()](IterableRouteAttrs::get_encap)\n- [.get_expires()](IterableRouteAttrs::get_expires)\n- [.get_pad()](IterableRouteAttrs::get_pad)\n- [.get_uid()](IterableRouteAttrs::get_uid)\n- [.get_ttl_propagate()](IterableRouteAttrs::get_ttl_propagate)\n- [.get_ip_proto()](IterableRouteAttrs::get_ip_proto)\n- [.get_sport()](IterableRouteAttrs::get_sport)\n- [.get_dport()](IterableRouteAttrs::get_dport)\n- [.get_nh_id()](IterableRouteAttrs::get_nh_id)\n- [.get_flowlabel()](IterableRouteAttrs::get_flowlabel)\n"]
2674    pub fn op_getroute_do(self, header: &Rtmsg) -> OpGetrouteDo<'buf> {
2675        let mut res = OpGetrouteDo::new(self, header);
2676        res.request
2677            .do_writeback(res.protocol(), "op-getroute-do", OpGetrouteDo::lookup);
2678        res
2679    }
2680    #[doc = "Create a new route\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_gateway()](PushRouteAttrs::push_gateway)\n- [.push_priority()](PushRouteAttrs::push_priority)\n- [.push_prefsrc()](PushRouteAttrs::push_prefsrc)\n- [.nested_metrics()](PushRouteAttrs::nested_metrics)\n- [.push_multipath()](PushRouteAttrs::push_multipath)\n- [.push_flow()](PushRouteAttrs::push_flow)\n- [.push_cacheinfo()](PushRouteAttrs::push_cacheinfo)\n- [.push_table()](PushRouteAttrs::push_table)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_mfc_stats()](PushRouteAttrs::push_mfc_stats)\n- [.push_via()](PushRouteAttrs::push_via)\n- [.push_newdst()](PushRouteAttrs::push_newdst)\n- [.push_pref()](PushRouteAttrs::push_pref)\n- [.push_encap_type()](PushRouteAttrs::push_encap_type)\n- [.push_encap()](PushRouteAttrs::push_encap)\n- [.push_expires()](PushRouteAttrs::push_expires)\n- [.push_pad()](PushRouteAttrs::push_pad)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ttl_propagate()](PushRouteAttrs::push_ttl_propagate)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_nh_id()](PushRouteAttrs::push_nh_id)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n"]
2681    pub fn op_newroute_do(self, header: &Rtmsg) -> OpNewrouteDo<'buf> {
2682        let mut res = OpNewrouteDo::new(self, header);
2683        res.request
2684            .do_writeback(res.protocol(), "op-newroute-do", OpNewrouteDo::lookup);
2685        res
2686    }
2687    #[doc = "Delete an existing route\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_gateway()](PushRouteAttrs::push_gateway)\n- [.push_priority()](PushRouteAttrs::push_priority)\n- [.push_prefsrc()](PushRouteAttrs::push_prefsrc)\n- [.nested_metrics()](PushRouteAttrs::nested_metrics)\n- [.push_multipath()](PushRouteAttrs::push_multipath)\n- [.push_flow()](PushRouteAttrs::push_flow)\n- [.push_cacheinfo()](PushRouteAttrs::push_cacheinfo)\n- [.push_table()](PushRouteAttrs::push_table)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_mfc_stats()](PushRouteAttrs::push_mfc_stats)\n- [.push_via()](PushRouteAttrs::push_via)\n- [.push_newdst()](PushRouteAttrs::push_newdst)\n- [.push_pref()](PushRouteAttrs::push_pref)\n- [.push_encap_type()](PushRouteAttrs::push_encap_type)\n- [.push_encap()](PushRouteAttrs::push_encap)\n- [.push_expires()](PushRouteAttrs::push_expires)\n- [.push_pad()](PushRouteAttrs::push_pad)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ttl_propagate()](PushRouteAttrs::push_ttl_propagate)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_nh_id()](PushRouteAttrs::push_nh_id)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n"]
2688    pub fn op_delroute_do(self, header: &Rtmsg) -> OpDelrouteDo<'buf> {
2689        let mut res = OpDelrouteDo::new(self, header);
2690        res.request
2691            .do_writeback(res.protocol(), "op-delroute-do", OpDelrouteDo::lookup);
2692        res
2693    }
2694}
2695#[cfg(test)]
2696mod generated_tests {
2697    use super::*;
2698    #[test]
2699    fn tests() {
2700        let _ = IterableRouteAttrs::get_cacheinfo;
2701        let _ = IterableRouteAttrs::get_dport;
2702        let _ = IterableRouteAttrs::get_dst;
2703        let _ = IterableRouteAttrs::get_encap;
2704        let _ = IterableRouteAttrs::get_encap_type;
2705        let _ = IterableRouteAttrs::get_expires;
2706        let _ = IterableRouteAttrs::get_flow;
2707        let _ = IterableRouteAttrs::get_flowlabel;
2708        let _ = IterableRouteAttrs::get_gateway;
2709        let _ = IterableRouteAttrs::get_iif;
2710        let _ = IterableRouteAttrs::get_ip_proto;
2711        let _ = IterableRouteAttrs::get_mark;
2712        let _ = IterableRouteAttrs::get_metrics;
2713        let _ = IterableRouteAttrs::get_mfc_stats;
2714        let _ = IterableRouteAttrs::get_multipath;
2715        let _ = IterableRouteAttrs::get_newdst;
2716        let _ = IterableRouteAttrs::get_nh_id;
2717        let _ = IterableRouteAttrs::get_oif;
2718        let _ = IterableRouteAttrs::get_pad;
2719        let _ = IterableRouteAttrs::get_pref;
2720        let _ = IterableRouteAttrs::get_prefsrc;
2721        let _ = IterableRouteAttrs::get_priority;
2722        let _ = IterableRouteAttrs::get_sport;
2723        let _ = IterableRouteAttrs::get_src;
2724        let _ = IterableRouteAttrs::get_table;
2725        let _ = IterableRouteAttrs::get_ttl_propagate;
2726        let _ = IterableRouteAttrs::get_uid;
2727        let _ = IterableRouteAttrs::get_via;
2728        let _ = PushRouteAttrs::<&mut Vec<u8>>::nested_metrics;
2729        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_cacheinfo;
2730        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_dport;
2731        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_dst;
2732        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_encap;
2733        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_encap_type;
2734        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_expires;
2735        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_flow;
2736        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_flowlabel;
2737        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_gateway;
2738        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_iif;
2739        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_ip_proto;
2740        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_mark;
2741        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_mfc_stats;
2742        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_multipath;
2743        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_newdst;
2744        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_nh_id;
2745        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_oif;
2746        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_pad;
2747        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_pref;
2748        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_prefsrc;
2749        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_priority;
2750        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_sport;
2751        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_src;
2752        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_table;
2753        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_ttl_propagate;
2754        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_uid;
2755        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_via;
2756    }
2757}