Skip to main content

netlink_bindings/rt-route/
mod.rs

1#![doc = "Route configuration over rtnetlink.\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "rt-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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 mut pos;
781        let mut r#type;
782        loop {
783            pos = self.pos;
784            r#type = None;
785            if self.buf.len() == self.pos {
786                return None;
787            }
788            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
789                self.pos = self.buf.len();
790                break;
791            };
792            r#type = Some(header.r#type);
793            let res = match header.r#type {
794                1u16 => RouteAttrs::Dst({
795                    let res = parse_ip(next);
796                    let Some(val) = res else { break };
797                    val
798                }),
799                2u16 => RouteAttrs::Src({
800                    let res = parse_ip(next);
801                    let Some(val) = res else { break };
802                    val
803                }),
804                3u16 => RouteAttrs::Iif({
805                    let res = parse_u32(next);
806                    let Some(val) = res else { break };
807                    val
808                }),
809                4u16 => RouteAttrs::Oif({
810                    let res = parse_u32(next);
811                    let Some(val) = res else { break };
812                    val
813                }),
814                5u16 => RouteAttrs::Gateway({
815                    let res = parse_ip(next);
816                    let Some(val) = res else { break };
817                    val
818                }),
819                6u16 => RouteAttrs::Priority({
820                    let res = parse_u32(next);
821                    let Some(val) = res else { break };
822                    val
823                }),
824                7u16 => RouteAttrs::Prefsrc({
825                    let res = parse_ip(next);
826                    let Some(val) = res else { break };
827                    val
828                }),
829                8u16 => RouteAttrs::Metrics({
830                    let res = Some(IterableMetrics::with_loc(next, self.orig_loc));
831                    let Some(val) = res else { break };
832                    val
833                }),
834                9u16 => RouteAttrs::Multipath({
835                    let res = Some(next);
836                    let Some(val) = res else { break };
837                    val
838                }),
839                10u16 => RouteAttrs::Protoinfo({
840                    let res = Some(next);
841                    let Some(val) = res else { break };
842                    val
843                }),
844                11u16 => RouteAttrs::Flow({
845                    let res = parse_u32(next);
846                    let Some(val) = res else { break };
847                    val
848                }),
849                12u16 => RouteAttrs::Cacheinfo({
850                    let res = Some(RtaCacheinfo::new_from_zeroed(next));
851                    let Some(val) = res else { break };
852                    val
853                }),
854                13u16 => RouteAttrs::Session({
855                    let res = Some(next);
856                    let Some(val) = res else { break };
857                    val
858                }),
859                14u16 => RouteAttrs::MpAlgo({
860                    let res = Some(next);
861                    let Some(val) = res else { break };
862                    val
863                }),
864                15u16 => RouteAttrs::Table({
865                    let res = parse_u32(next);
866                    let Some(val) = res else { break };
867                    val
868                }),
869                16u16 => RouteAttrs::Mark({
870                    let res = parse_u32(next);
871                    let Some(val) = res else { break };
872                    val
873                }),
874                17u16 => RouteAttrs::MfcStats({
875                    let res = Some(next);
876                    let Some(val) = res else { break };
877                    val
878                }),
879                18u16 => RouteAttrs::Via({
880                    let res = Some(next);
881                    let Some(val) = res else { break };
882                    val
883                }),
884                19u16 => RouteAttrs::Newdst({
885                    let res = Some(next);
886                    let Some(val) = res else { break };
887                    val
888                }),
889                20u16 => RouteAttrs::Pref({
890                    let res = parse_u8(next);
891                    let Some(val) = res else { break };
892                    val
893                }),
894                21u16 => RouteAttrs::EncapType({
895                    let res = parse_u16(next);
896                    let Some(val) = res else { break };
897                    val
898                }),
899                22u16 => RouteAttrs::Encap({
900                    let res = Some(next);
901                    let Some(val) = res else { break };
902                    val
903                }),
904                23u16 => RouteAttrs::Expires({
905                    let res = parse_u32(next);
906                    let Some(val) = res else { break };
907                    val
908                }),
909                24u16 => RouteAttrs::Pad({
910                    let res = Some(next);
911                    let Some(val) = res else { break };
912                    val
913                }),
914                25u16 => RouteAttrs::Uid({
915                    let res = parse_u32(next);
916                    let Some(val) = res else { break };
917                    val
918                }),
919                26u16 => RouteAttrs::TtlPropagate({
920                    let res = parse_u8(next);
921                    let Some(val) = res else { break };
922                    val
923                }),
924                27u16 => RouteAttrs::IpProto({
925                    let res = parse_u8(next);
926                    let Some(val) = res else { break };
927                    val
928                }),
929                28u16 => RouteAttrs::Sport({
930                    let res = parse_u16(next);
931                    let Some(val) = res else { break };
932                    val
933                }),
934                29u16 => RouteAttrs::Dport({
935                    let res = parse_u16(next);
936                    let Some(val) = res else { break };
937                    val
938                }),
939                30u16 => RouteAttrs::NhId({
940                    let res = parse_u32(next);
941                    let Some(val) = res else { break };
942                    val
943                }),
944                31u16 => RouteAttrs::Flowlabel({
945                    let res = parse_be_u32(next);
946                    let Some(val) = res else { break };
947                    val
948                }),
949                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
950                n => continue,
951            };
952            return Some(Ok(res));
953        }
954        Some(Err(ErrorContext::new(
955            "RouteAttrs",
956            r#type.and_then(|t| RouteAttrs::attr_from_type(t)),
957            self.orig_loc,
958            self.buf.as_ptr().wrapping_add(pos) as usize,
959        )))
960    }
961}
962impl<'a> std::fmt::Debug for IterableRouteAttrs<'_> {
963    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
964        let mut fmt = f.debug_struct("RouteAttrs");
965        for attr in self.clone() {
966            let attr = match attr {
967                Ok(a) => a,
968                Err(err) => {
969                    fmt.finish()?;
970                    f.write_str("Err(")?;
971                    err.fmt(f)?;
972                    return f.write_str(")");
973                }
974            };
975            match attr {
976                RouteAttrs::Dst(val) => fmt.field("Dst", &val),
977                RouteAttrs::Src(val) => fmt.field("Src", &val),
978                RouteAttrs::Iif(val) => fmt.field("Iif", &val),
979                RouteAttrs::Oif(val) => fmt.field("Oif", &val),
980                RouteAttrs::Gateway(val) => fmt.field("Gateway", &val),
981                RouteAttrs::Priority(val) => fmt.field("Priority", &val),
982                RouteAttrs::Prefsrc(val) => fmt.field("Prefsrc", &val),
983                RouteAttrs::Metrics(val) => fmt.field("Metrics", &val),
984                RouteAttrs::Multipath(val) => fmt.field("Multipath", &val),
985                RouteAttrs::Protoinfo(val) => fmt.field("Protoinfo", &val),
986                RouteAttrs::Flow(val) => fmt.field("Flow", &val),
987                RouteAttrs::Cacheinfo(val) => fmt.field("Cacheinfo", &val),
988                RouteAttrs::Session(val) => fmt.field("Session", &val),
989                RouteAttrs::MpAlgo(val) => fmt.field("MpAlgo", &val),
990                RouteAttrs::Table(val) => fmt.field("Table", &val),
991                RouteAttrs::Mark(val) => fmt.field("Mark", &val),
992                RouteAttrs::MfcStats(val) => fmt.field("MfcStats", &val),
993                RouteAttrs::Via(val) => fmt.field("Via", &val),
994                RouteAttrs::Newdst(val) => fmt.field("Newdst", &val),
995                RouteAttrs::Pref(val) => fmt.field("Pref", &val),
996                RouteAttrs::EncapType(val) => fmt.field("EncapType", &val),
997                RouteAttrs::Encap(val) => fmt.field("Encap", &val),
998                RouteAttrs::Expires(val) => fmt.field("Expires", &val),
999                RouteAttrs::Pad(val) => fmt.field("Pad", &val),
1000                RouteAttrs::Uid(val) => fmt.field("Uid", &val),
1001                RouteAttrs::TtlPropagate(val) => fmt.field("TtlPropagate", &val),
1002                RouteAttrs::IpProto(val) => fmt.field("IpProto", &val),
1003                RouteAttrs::Sport(val) => fmt.field("Sport", &val),
1004                RouteAttrs::Dport(val) => fmt.field("Dport", &val),
1005                RouteAttrs::NhId(val) => fmt.field("NhId", &val),
1006                RouteAttrs::Flowlabel(val) => fmt.field("Flowlabel", &val),
1007            };
1008        }
1009        fmt.finish()
1010    }
1011}
1012impl IterableRouteAttrs<'_> {
1013    pub fn lookup_attr(
1014        &self,
1015        offset: usize,
1016        missing_type: Option<u16>,
1017    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1018        let mut stack = Vec::new();
1019        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1020        if missing_type.is_some() && cur == offset {
1021            stack.push(("RouteAttrs", offset));
1022            return (
1023                stack,
1024                missing_type.and_then(|t| RouteAttrs::attr_from_type(t)),
1025            );
1026        }
1027        if cur > offset || cur + self.buf.len() < offset {
1028            return (stack, None);
1029        }
1030        let mut attrs = self.clone();
1031        let mut last_off = cur + attrs.pos;
1032        let mut missing = None;
1033        while let Some(attr) = attrs.next() {
1034            let Ok(attr) = attr else { break };
1035            match attr {
1036                RouteAttrs::Dst(val) => {
1037                    if last_off == offset {
1038                        stack.push(("Dst", last_off));
1039                        break;
1040                    }
1041                }
1042                RouteAttrs::Src(val) => {
1043                    if last_off == offset {
1044                        stack.push(("Src", last_off));
1045                        break;
1046                    }
1047                }
1048                RouteAttrs::Iif(val) => {
1049                    if last_off == offset {
1050                        stack.push(("Iif", last_off));
1051                        break;
1052                    }
1053                }
1054                RouteAttrs::Oif(val) => {
1055                    if last_off == offset {
1056                        stack.push(("Oif", last_off));
1057                        break;
1058                    }
1059                }
1060                RouteAttrs::Gateway(val) => {
1061                    if last_off == offset {
1062                        stack.push(("Gateway", last_off));
1063                        break;
1064                    }
1065                }
1066                RouteAttrs::Priority(val) => {
1067                    if last_off == offset {
1068                        stack.push(("Priority", last_off));
1069                        break;
1070                    }
1071                }
1072                RouteAttrs::Prefsrc(val) => {
1073                    if last_off == offset {
1074                        stack.push(("Prefsrc", last_off));
1075                        break;
1076                    }
1077                }
1078                RouteAttrs::Metrics(val) => {
1079                    (stack, missing) = val.lookup_attr(offset, missing_type);
1080                    if !stack.is_empty() {
1081                        break;
1082                    }
1083                }
1084                RouteAttrs::Multipath(val) => {
1085                    if last_off == offset {
1086                        stack.push(("Multipath", last_off));
1087                        break;
1088                    }
1089                }
1090                RouteAttrs::Protoinfo(val) => {
1091                    if last_off == offset {
1092                        stack.push(("Protoinfo", last_off));
1093                        break;
1094                    }
1095                }
1096                RouteAttrs::Flow(val) => {
1097                    if last_off == offset {
1098                        stack.push(("Flow", last_off));
1099                        break;
1100                    }
1101                }
1102                RouteAttrs::Cacheinfo(val) => {
1103                    if last_off == offset {
1104                        stack.push(("Cacheinfo", last_off));
1105                        break;
1106                    }
1107                }
1108                RouteAttrs::Session(val) => {
1109                    if last_off == offset {
1110                        stack.push(("Session", last_off));
1111                        break;
1112                    }
1113                }
1114                RouteAttrs::MpAlgo(val) => {
1115                    if last_off == offset {
1116                        stack.push(("MpAlgo", last_off));
1117                        break;
1118                    }
1119                }
1120                RouteAttrs::Table(val) => {
1121                    if last_off == offset {
1122                        stack.push(("Table", last_off));
1123                        break;
1124                    }
1125                }
1126                RouteAttrs::Mark(val) => {
1127                    if last_off == offset {
1128                        stack.push(("Mark", last_off));
1129                        break;
1130                    }
1131                }
1132                RouteAttrs::MfcStats(val) => {
1133                    if last_off == offset {
1134                        stack.push(("MfcStats", last_off));
1135                        break;
1136                    }
1137                }
1138                RouteAttrs::Via(val) => {
1139                    if last_off == offset {
1140                        stack.push(("Via", last_off));
1141                        break;
1142                    }
1143                }
1144                RouteAttrs::Newdst(val) => {
1145                    if last_off == offset {
1146                        stack.push(("Newdst", last_off));
1147                        break;
1148                    }
1149                }
1150                RouteAttrs::Pref(val) => {
1151                    if last_off == offset {
1152                        stack.push(("Pref", last_off));
1153                        break;
1154                    }
1155                }
1156                RouteAttrs::EncapType(val) => {
1157                    if last_off == offset {
1158                        stack.push(("EncapType", last_off));
1159                        break;
1160                    }
1161                }
1162                RouteAttrs::Encap(val) => {
1163                    if last_off == offset {
1164                        stack.push(("Encap", last_off));
1165                        break;
1166                    }
1167                }
1168                RouteAttrs::Expires(val) => {
1169                    if last_off == offset {
1170                        stack.push(("Expires", last_off));
1171                        break;
1172                    }
1173                }
1174                RouteAttrs::Pad(val) => {
1175                    if last_off == offset {
1176                        stack.push(("Pad", last_off));
1177                        break;
1178                    }
1179                }
1180                RouteAttrs::Uid(val) => {
1181                    if last_off == offset {
1182                        stack.push(("Uid", last_off));
1183                        break;
1184                    }
1185                }
1186                RouteAttrs::TtlPropagate(val) => {
1187                    if last_off == offset {
1188                        stack.push(("TtlPropagate", last_off));
1189                        break;
1190                    }
1191                }
1192                RouteAttrs::IpProto(val) => {
1193                    if last_off == offset {
1194                        stack.push(("IpProto", last_off));
1195                        break;
1196                    }
1197                }
1198                RouteAttrs::Sport(val) => {
1199                    if last_off == offset {
1200                        stack.push(("Sport", last_off));
1201                        break;
1202                    }
1203                }
1204                RouteAttrs::Dport(val) => {
1205                    if last_off == offset {
1206                        stack.push(("Dport", last_off));
1207                        break;
1208                    }
1209                }
1210                RouteAttrs::NhId(val) => {
1211                    if last_off == offset {
1212                        stack.push(("NhId", last_off));
1213                        break;
1214                    }
1215                }
1216                RouteAttrs::Flowlabel(val) => {
1217                    if last_off == offset {
1218                        stack.push(("Flowlabel", last_off));
1219                        break;
1220                    }
1221                }
1222                _ => {}
1223            };
1224            last_off = cur + attrs.pos;
1225        }
1226        if !stack.is_empty() {
1227            stack.push(("RouteAttrs", cur));
1228        }
1229        (stack, missing)
1230    }
1231}
1232#[derive(Clone)]
1233pub enum Metrics<'a> {
1234    Lock(u32),
1235    Mtu(u32),
1236    Window(u32),
1237    Rtt(u32),
1238    Rttvar(u32),
1239    Ssthresh(u32),
1240    Cwnd(u32),
1241    Advmss(u32),
1242    Reordering(u32),
1243    Hoplimit(u32),
1244    Initcwnd(u32),
1245    Features(u32),
1246    RtoMin(u32),
1247    Initrwnd(u32),
1248    Quickack(u32),
1249    CcAlgo(&'a CStr),
1250    FastopenNoCookie(u32),
1251}
1252impl<'a> IterableMetrics<'a> {
1253    pub fn get_lock(&self) -> Result<u32, ErrorContext> {
1254        let mut iter = self.clone();
1255        iter.pos = 0;
1256        for attr in iter {
1257            if let Ok(Metrics::Lock(val)) = attr {
1258                return Ok(val);
1259            }
1260        }
1261        Err(ErrorContext::new_missing(
1262            "Metrics",
1263            "Lock",
1264            self.orig_loc,
1265            self.buf.as_ptr() as usize,
1266        ))
1267    }
1268    pub fn get_mtu(&self) -> Result<u32, ErrorContext> {
1269        let mut iter = self.clone();
1270        iter.pos = 0;
1271        for attr in iter {
1272            if let Ok(Metrics::Mtu(val)) = attr {
1273                return Ok(val);
1274            }
1275        }
1276        Err(ErrorContext::new_missing(
1277            "Metrics",
1278            "Mtu",
1279            self.orig_loc,
1280            self.buf.as_ptr() as usize,
1281        ))
1282    }
1283    pub fn get_window(&self) -> Result<u32, ErrorContext> {
1284        let mut iter = self.clone();
1285        iter.pos = 0;
1286        for attr in iter {
1287            if let Ok(Metrics::Window(val)) = attr {
1288                return Ok(val);
1289            }
1290        }
1291        Err(ErrorContext::new_missing(
1292            "Metrics",
1293            "Window",
1294            self.orig_loc,
1295            self.buf.as_ptr() as usize,
1296        ))
1297    }
1298    pub fn get_rtt(&self) -> Result<u32, ErrorContext> {
1299        let mut iter = self.clone();
1300        iter.pos = 0;
1301        for attr in iter {
1302            if let Ok(Metrics::Rtt(val)) = attr {
1303                return Ok(val);
1304            }
1305        }
1306        Err(ErrorContext::new_missing(
1307            "Metrics",
1308            "Rtt",
1309            self.orig_loc,
1310            self.buf.as_ptr() as usize,
1311        ))
1312    }
1313    pub fn get_rttvar(&self) -> Result<u32, ErrorContext> {
1314        let mut iter = self.clone();
1315        iter.pos = 0;
1316        for attr in iter {
1317            if let Ok(Metrics::Rttvar(val)) = attr {
1318                return Ok(val);
1319            }
1320        }
1321        Err(ErrorContext::new_missing(
1322            "Metrics",
1323            "Rttvar",
1324            self.orig_loc,
1325            self.buf.as_ptr() as usize,
1326        ))
1327    }
1328    pub fn get_ssthresh(&self) -> Result<u32, ErrorContext> {
1329        let mut iter = self.clone();
1330        iter.pos = 0;
1331        for attr in iter {
1332            if let Ok(Metrics::Ssthresh(val)) = attr {
1333                return Ok(val);
1334            }
1335        }
1336        Err(ErrorContext::new_missing(
1337            "Metrics",
1338            "Ssthresh",
1339            self.orig_loc,
1340            self.buf.as_ptr() as usize,
1341        ))
1342    }
1343    pub fn get_cwnd(&self) -> Result<u32, ErrorContext> {
1344        let mut iter = self.clone();
1345        iter.pos = 0;
1346        for attr in iter {
1347            if let Ok(Metrics::Cwnd(val)) = attr {
1348                return Ok(val);
1349            }
1350        }
1351        Err(ErrorContext::new_missing(
1352            "Metrics",
1353            "Cwnd",
1354            self.orig_loc,
1355            self.buf.as_ptr() as usize,
1356        ))
1357    }
1358    pub fn get_advmss(&self) -> Result<u32, ErrorContext> {
1359        let mut iter = self.clone();
1360        iter.pos = 0;
1361        for attr in iter {
1362            if let Ok(Metrics::Advmss(val)) = attr {
1363                return Ok(val);
1364            }
1365        }
1366        Err(ErrorContext::new_missing(
1367            "Metrics",
1368            "Advmss",
1369            self.orig_loc,
1370            self.buf.as_ptr() as usize,
1371        ))
1372    }
1373    pub fn get_reordering(&self) -> Result<u32, ErrorContext> {
1374        let mut iter = self.clone();
1375        iter.pos = 0;
1376        for attr in iter {
1377            if let Ok(Metrics::Reordering(val)) = attr {
1378                return Ok(val);
1379            }
1380        }
1381        Err(ErrorContext::new_missing(
1382            "Metrics",
1383            "Reordering",
1384            self.orig_loc,
1385            self.buf.as_ptr() as usize,
1386        ))
1387    }
1388    pub fn get_hoplimit(&self) -> Result<u32, ErrorContext> {
1389        let mut iter = self.clone();
1390        iter.pos = 0;
1391        for attr in iter {
1392            if let Ok(Metrics::Hoplimit(val)) = attr {
1393                return Ok(val);
1394            }
1395        }
1396        Err(ErrorContext::new_missing(
1397            "Metrics",
1398            "Hoplimit",
1399            self.orig_loc,
1400            self.buf.as_ptr() as usize,
1401        ))
1402    }
1403    pub fn get_initcwnd(&self) -> Result<u32, ErrorContext> {
1404        let mut iter = self.clone();
1405        iter.pos = 0;
1406        for attr in iter {
1407            if let Ok(Metrics::Initcwnd(val)) = attr {
1408                return Ok(val);
1409            }
1410        }
1411        Err(ErrorContext::new_missing(
1412            "Metrics",
1413            "Initcwnd",
1414            self.orig_loc,
1415            self.buf.as_ptr() as usize,
1416        ))
1417    }
1418    pub fn get_features(&self) -> Result<u32, ErrorContext> {
1419        let mut iter = self.clone();
1420        iter.pos = 0;
1421        for attr in iter {
1422            if let Ok(Metrics::Features(val)) = attr {
1423                return Ok(val);
1424            }
1425        }
1426        Err(ErrorContext::new_missing(
1427            "Metrics",
1428            "Features",
1429            self.orig_loc,
1430            self.buf.as_ptr() as usize,
1431        ))
1432    }
1433    pub fn get_rto_min(&self) -> Result<u32, ErrorContext> {
1434        let mut iter = self.clone();
1435        iter.pos = 0;
1436        for attr in iter {
1437            if let Ok(Metrics::RtoMin(val)) = attr {
1438                return Ok(val);
1439            }
1440        }
1441        Err(ErrorContext::new_missing(
1442            "Metrics",
1443            "RtoMin",
1444            self.orig_loc,
1445            self.buf.as_ptr() as usize,
1446        ))
1447    }
1448    pub fn get_initrwnd(&self) -> Result<u32, ErrorContext> {
1449        let mut iter = self.clone();
1450        iter.pos = 0;
1451        for attr in iter {
1452            if let Ok(Metrics::Initrwnd(val)) = attr {
1453                return Ok(val);
1454            }
1455        }
1456        Err(ErrorContext::new_missing(
1457            "Metrics",
1458            "Initrwnd",
1459            self.orig_loc,
1460            self.buf.as_ptr() as usize,
1461        ))
1462    }
1463    pub fn get_quickack(&self) -> Result<u32, ErrorContext> {
1464        let mut iter = self.clone();
1465        iter.pos = 0;
1466        for attr in iter {
1467            if let Ok(Metrics::Quickack(val)) = attr {
1468                return Ok(val);
1469            }
1470        }
1471        Err(ErrorContext::new_missing(
1472            "Metrics",
1473            "Quickack",
1474            self.orig_loc,
1475            self.buf.as_ptr() as usize,
1476        ))
1477    }
1478    pub fn get_cc_algo(&self) -> Result<&'a CStr, ErrorContext> {
1479        let mut iter = self.clone();
1480        iter.pos = 0;
1481        for attr in iter {
1482            if let Ok(Metrics::CcAlgo(val)) = attr {
1483                return Ok(val);
1484            }
1485        }
1486        Err(ErrorContext::new_missing(
1487            "Metrics",
1488            "CcAlgo",
1489            self.orig_loc,
1490            self.buf.as_ptr() as usize,
1491        ))
1492    }
1493    pub fn get_fastopen_no_cookie(&self) -> Result<u32, ErrorContext> {
1494        let mut iter = self.clone();
1495        iter.pos = 0;
1496        for attr in iter {
1497            if let Ok(Metrics::FastopenNoCookie(val)) = attr {
1498                return Ok(val);
1499            }
1500        }
1501        Err(ErrorContext::new_missing(
1502            "Metrics",
1503            "FastopenNoCookie",
1504            self.orig_loc,
1505            self.buf.as_ptr() as usize,
1506        ))
1507    }
1508}
1509impl Metrics<'_> {
1510    pub fn new<'a>(buf: &'a [u8]) -> IterableMetrics<'a> {
1511        IterableMetrics::with_loc(buf, buf.as_ptr() as usize)
1512    }
1513    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1514        let res = match r#type {
1515            0u16 => "Unspec",
1516            1u16 => "Lock",
1517            2u16 => "Mtu",
1518            3u16 => "Window",
1519            4u16 => "Rtt",
1520            5u16 => "Rttvar",
1521            6u16 => "Ssthresh",
1522            7u16 => "Cwnd",
1523            8u16 => "Advmss",
1524            9u16 => "Reordering",
1525            10u16 => "Hoplimit",
1526            11u16 => "Initcwnd",
1527            12u16 => "Features",
1528            13u16 => "RtoMin",
1529            14u16 => "Initrwnd",
1530            15u16 => "Quickack",
1531            16u16 => "CcAlgo",
1532            17u16 => "FastopenNoCookie",
1533            _ => return None,
1534        };
1535        Some(res)
1536    }
1537}
1538#[derive(Clone, Copy, Default)]
1539pub struct IterableMetrics<'a> {
1540    buf: &'a [u8],
1541    pos: usize,
1542    orig_loc: usize,
1543}
1544impl<'a> IterableMetrics<'a> {
1545    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1546        Self {
1547            buf,
1548            pos: 0,
1549            orig_loc,
1550        }
1551    }
1552    pub fn get_buf(&self) -> &'a [u8] {
1553        self.buf
1554    }
1555}
1556impl<'a> Iterator for IterableMetrics<'a> {
1557    type Item = Result<Metrics<'a>, ErrorContext>;
1558    fn next(&mut self) -> Option<Self::Item> {
1559        let mut pos;
1560        let mut r#type;
1561        loop {
1562            pos = self.pos;
1563            r#type = None;
1564            if self.buf.len() == self.pos {
1565                return None;
1566            }
1567            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1568                self.pos = self.buf.len();
1569                break;
1570            };
1571            r#type = Some(header.r#type);
1572            let res = match header.r#type {
1573                1u16 => Metrics::Lock({
1574                    let res = parse_u32(next);
1575                    let Some(val) = res else { break };
1576                    val
1577                }),
1578                2u16 => Metrics::Mtu({
1579                    let res = parse_u32(next);
1580                    let Some(val) = res else { break };
1581                    val
1582                }),
1583                3u16 => Metrics::Window({
1584                    let res = parse_u32(next);
1585                    let Some(val) = res else { break };
1586                    val
1587                }),
1588                4u16 => Metrics::Rtt({
1589                    let res = parse_u32(next);
1590                    let Some(val) = res else { break };
1591                    val
1592                }),
1593                5u16 => Metrics::Rttvar({
1594                    let res = parse_u32(next);
1595                    let Some(val) = res else { break };
1596                    val
1597                }),
1598                6u16 => Metrics::Ssthresh({
1599                    let res = parse_u32(next);
1600                    let Some(val) = res else { break };
1601                    val
1602                }),
1603                7u16 => Metrics::Cwnd({
1604                    let res = parse_u32(next);
1605                    let Some(val) = res else { break };
1606                    val
1607                }),
1608                8u16 => Metrics::Advmss({
1609                    let res = parse_u32(next);
1610                    let Some(val) = res else { break };
1611                    val
1612                }),
1613                9u16 => Metrics::Reordering({
1614                    let res = parse_u32(next);
1615                    let Some(val) = res else { break };
1616                    val
1617                }),
1618                10u16 => Metrics::Hoplimit({
1619                    let res = parse_u32(next);
1620                    let Some(val) = res else { break };
1621                    val
1622                }),
1623                11u16 => Metrics::Initcwnd({
1624                    let res = parse_u32(next);
1625                    let Some(val) = res else { break };
1626                    val
1627                }),
1628                12u16 => Metrics::Features({
1629                    let res = parse_u32(next);
1630                    let Some(val) = res else { break };
1631                    val
1632                }),
1633                13u16 => Metrics::RtoMin({
1634                    let res = parse_u32(next);
1635                    let Some(val) = res else { break };
1636                    val
1637                }),
1638                14u16 => Metrics::Initrwnd({
1639                    let res = parse_u32(next);
1640                    let Some(val) = res else { break };
1641                    val
1642                }),
1643                15u16 => Metrics::Quickack({
1644                    let res = parse_u32(next);
1645                    let Some(val) = res else { break };
1646                    val
1647                }),
1648                16u16 => Metrics::CcAlgo({
1649                    let res = CStr::from_bytes_with_nul(next).ok();
1650                    let Some(val) = res else { break };
1651                    val
1652                }),
1653                17u16 => Metrics::FastopenNoCookie({
1654                    let res = parse_u32(next);
1655                    let Some(val) = res else { break };
1656                    val
1657                }),
1658                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1659                n => continue,
1660            };
1661            return Some(Ok(res));
1662        }
1663        Some(Err(ErrorContext::new(
1664            "Metrics",
1665            r#type.and_then(|t| Metrics::attr_from_type(t)),
1666            self.orig_loc,
1667            self.buf.as_ptr().wrapping_add(pos) as usize,
1668        )))
1669    }
1670}
1671impl<'a> std::fmt::Debug for IterableMetrics<'_> {
1672    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1673        let mut fmt = f.debug_struct("Metrics");
1674        for attr in self.clone() {
1675            let attr = match attr {
1676                Ok(a) => a,
1677                Err(err) => {
1678                    fmt.finish()?;
1679                    f.write_str("Err(")?;
1680                    err.fmt(f)?;
1681                    return f.write_str(")");
1682                }
1683            };
1684            match attr {
1685                Metrics::Lock(val) => fmt.field("Lock", &val),
1686                Metrics::Mtu(val) => fmt.field("Mtu", &val),
1687                Metrics::Window(val) => fmt.field("Window", &val),
1688                Metrics::Rtt(val) => fmt.field("Rtt", &val),
1689                Metrics::Rttvar(val) => fmt.field("Rttvar", &val),
1690                Metrics::Ssthresh(val) => fmt.field("Ssthresh", &val),
1691                Metrics::Cwnd(val) => fmt.field("Cwnd", &val),
1692                Metrics::Advmss(val) => fmt.field("Advmss", &val),
1693                Metrics::Reordering(val) => fmt.field("Reordering", &val),
1694                Metrics::Hoplimit(val) => fmt.field("Hoplimit", &val),
1695                Metrics::Initcwnd(val) => fmt.field("Initcwnd", &val),
1696                Metrics::Features(val) => fmt.field("Features", &val),
1697                Metrics::RtoMin(val) => fmt.field("RtoMin", &val),
1698                Metrics::Initrwnd(val) => fmt.field("Initrwnd", &val),
1699                Metrics::Quickack(val) => fmt.field("Quickack", &val),
1700                Metrics::CcAlgo(val) => fmt.field("CcAlgo", &val),
1701                Metrics::FastopenNoCookie(val) => fmt.field("FastopenNoCookie", &val),
1702            };
1703        }
1704        fmt.finish()
1705    }
1706}
1707impl IterableMetrics<'_> {
1708    pub fn lookup_attr(
1709        &self,
1710        offset: usize,
1711        missing_type: Option<u16>,
1712    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1713        let mut stack = Vec::new();
1714        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1715        if missing_type.is_some() && cur == offset {
1716            stack.push(("Metrics", offset));
1717            return (stack, missing_type.and_then(|t| Metrics::attr_from_type(t)));
1718        }
1719        if cur > offset || cur + self.buf.len() < offset {
1720            return (stack, None);
1721        }
1722        let mut attrs = self.clone();
1723        let mut last_off = cur + attrs.pos;
1724        while let Some(attr) = attrs.next() {
1725            let Ok(attr) = attr else { break };
1726            match attr {
1727                Metrics::Lock(val) => {
1728                    if last_off == offset {
1729                        stack.push(("Lock", last_off));
1730                        break;
1731                    }
1732                }
1733                Metrics::Mtu(val) => {
1734                    if last_off == offset {
1735                        stack.push(("Mtu", last_off));
1736                        break;
1737                    }
1738                }
1739                Metrics::Window(val) => {
1740                    if last_off == offset {
1741                        stack.push(("Window", last_off));
1742                        break;
1743                    }
1744                }
1745                Metrics::Rtt(val) => {
1746                    if last_off == offset {
1747                        stack.push(("Rtt", last_off));
1748                        break;
1749                    }
1750                }
1751                Metrics::Rttvar(val) => {
1752                    if last_off == offset {
1753                        stack.push(("Rttvar", last_off));
1754                        break;
1755                    }
1756                }
1757                Metrics::Ssthresh(val) => {
1758                    if last_off == offset {
1759                        stack.push(("Ssthresh", last_off));
1760                        break;
1761                    }
1762                }
1763                Metrics::Cwnd(val) => {
1764                    if last_off == offset {
1765                        stack.push(("Cwnd", last_off));
1766                        break;
1767                    }
1768                }
1769                Metrics::Advmss(val) => {
1770                    if last_off == offset {
1771                        stack.push(("Advmss", last_off));
1772                        break;
1773                    }
1774                }
1775                Metrics::Reordering(val) => {
1776                    if last_off == offset {
1777                        stack.push(("Reordering", last_off));
1778                        break;
1779                    }
1780                }
1781                Metrics::Hoplimit(val) => {
1782                    if last_off == offset {
1783                        stack.push(("Hoplimit", last_off));
1784                        break;
1785                    }
1786                }
1787                Metrics::Initcwnd(val) => {
1788                    if last_off == offset {
1789                        stack.push(("Initcwnd", last_off));
1790                        break;
1791                    }
1792                }
1793                Metrics::Features(val) => {
1794                    if last_off == offset {
1795                        stack.push(("Features", last_off));
1796                        break;
1797                    }
1798                }
1799                Metrics::RtoMin(val) => {
1800                    if last_off == offset {
1801                        stack.push(("RtoMin", last_off));
1802                        break;
1803                    }
1804                }
1805                Metrics::Initrwnd(val) => {
1806                    if last_off == offset {
1807                        stack.push(("Initrwnd", last_off));
1808                        break;
1809                    }
1810                }
1811                Metrics::Quickack(val) => {
1812                    if last_off == offset {
1813                        stack.push(("Quickack", last_off));
1814                        break;
1815                    }
1816                }
1817                Metrics::CcAlgo(val) => {
1818                    if last_off == offset {
1819                        stack.push(("CcAlgo", last_off));
1820                        break;
1821                    }
1822                }
1823                Metrics::FastopenNoCookie(val) => {
1824                    if last_off == offset {
1825                        stack.push(("FastopenNoCookie", last_off));
1826                        break;
1827                    }
1828                }
1829                _ => {}
1830            };
1831            last_off = cur + attrs.pos;
1832        }
1833        if !stack.is_empty() {
1834            stack.push(("Metrics", cur));
1835        }
1836        (stack, None)
1837    }
1838}
1839pub struct PushRouteAttrs<Prev: Pusher> {
1840    pub(crate) prev: Option<Prev>,
1841    pub(crate) header_offset: Option<usize>,
1842}
1843impl<Prev: Pusher> Pusher for PushRouteAttrs<Prev> {
1844    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1845        self.prev.as_mut().unwrap().as_vec_mut()
1846    }
1847    fn as_vec(&self) -> &Vec<u8> {
1848        self.prev.as_ref().unwrap().as_vec()
1849    }
1850}
1851impl<Prev: Pusher> PushRouteAttrs<Prev> {
1852    pub fn new(prev: Prev) -> Self {
1853        Self {
1854            prev: Some(prev),
1855            header_offset: None,
1856        }
1857    }
1858    pub fn end_nested(mut self) -> Prev {
1859        let mut prev = self.prev.take().unwrap();
1860        if let Some(header_offset) = &self.header_offset {
1861            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1862        }
1863        prev
1864    }
1865    pub fn push_dst(mut self, value: std::net::IpAddr) -> Self {
1866        push_header(self.as_vec_mut(), 1u16, {
1867            match &value {
1868                IpAddr::V4(_) => 4,
1869                IpAddr::V6(_) => 16,
1870            }
1871        } as u16);
1872        encode_ip(self.as_vec_mut(), value);
1873        self
1874    }
1875    pub fn push_src(mut self, value: std::net::IpAddr) -> Self {
1876        push_header(self.as_vec_mut(), 2u16, {
1877            match &value {
1878                IpAddr::V4(_) => 4,
1879                IpAddr::V6(_) => 16,
1880            }
1881        } as u16);
1882        encode_ip(self.as_vec_mut(), value);
1883        self
1884    }
1885    pub fn push_iif(mut self, value: u32) -> Self {
1886        push_header(self.as_vec_mut(), 3u16, 4 as u16);
1887        self.as_vec_mut().extend(value.to_ne_bytes());
1888        self
1889    }
1890    pub fn push_oif(mut self, value: u32) -> Self {
1891        push_header(self.as_vec_mut(), 4u16, 4 as u16);
1892        self.as_vec_mut().extend(value.to_ne_bytes());
1893        self
1894    }
1895    pub fn push_gateway(mut self, value: std::net::IpAddr) -> Self {
1896        push_header(self.as_vec_mut(), 5u16, {
1897            match &value {
1898                IpAddr::V4(_) => 4,
1899                IpAddr::V6(_) => 16,
1900            }
1901        } as u16);
1902        encode_ip(self.as_vec_mut(), value);
1903        self
1904    }
1905    pub fn push_priority(mut self, value: u32) -> Self {
1906        push_header(self.as_vec_mut(), 6u16, 4 as u16);
1907        self.as_vec_mut().extend(value.to_ne_bytes());
1908        self
1909    }
1910    pub fn push_prefsrc(mut self, value: std::net::IpAddr) -> Self {
1911        push_header(self.as_vec_mut(), 7u16, {
1912            match &value {
1913                IpAddr::V4(_) => 4,
1914                IpAddr::V6(_) => 16,
1915            }
1916        } as u16);
1917        encode_ip(self.as_vec_mut(), value);
1918        self
1919    }
1920    pub fn nested_metrics(mut self) -> PushMetrics<Self> {
1921        let header_offset = push_nested_header(self.as_vec_mut(), 8u16);
1922        PushMetrics {
1923            prev: Some(self),
1924            header_offset: Some(header_offset),
1925        }
1926    }
1927    pub fn push_multipath(mut self, value: &[u8]) -> Self {
1928        push_header(self.as_vec_mut(), 9u16, value.len() as u16);
1929        self.as_vec_mut().extend(value);
1930        self
1931    }
1932    pub fn push_protoinfo(mut self, value: &[u8]) -> Self {
1933        push_header(self.as_vec_mut(), 10u16, value.len() as u16);
1934        self.as_vec_mut().extend(value);
1935        self
1936    }
1937    pub fn push_flow(mut self, value: u32) -> Self {
1938        push_header(self.as_vec_mut(), 11u16, 4 as u16);
1939        self.as_vec_mut().extend(value.to_ne_bytes());
1940        self
1941    }
1942    pub fn push_cacheinfo(mut self, value: RtaCacheinfo) -> Self {
1943        push_header(self.as_vec_mut(), 12u16, value.as_slice().len() as u16);
1944        self.as_vec_mut().extend(value.as_slice());
1945        self
1946    }
1947    pub fn push_session(mut self, value: &[u8]) -> Self {
1948        push_header(self.as_vec_mut(), 13u16, value.len() as u16);
1949        self.as_vec_mut().extend(value);
1950        self
1951    }
1952    pub fn push_mp_algo(mut self, value: &[u8]) -> Self {
1953        push_header(self.as_vec_mut(), 14u16, value.len() as u16);
1954        self.as_vec_mut().extend(value);
1955        self
1956    }
1957    pub fn push_table(mut self, value: u32) -> Self {
1958        push_header(self.as_vec_mut(), 15u16, 4 as u16);
1959        self.as_vec_mut().extend(value.to_ne_bytes());
1960        self
1961    }
1962    pub fn push_mark(mut self, value: u32) -> Self {
1963        push_header(self.as_vec_mut(), 16u16, 4 as u16);
1964        self.as_vec_mut().extend(value.to_ne_bytes());
1965        self
1966    }
1967    pub fn push_mfc_stats(mut self, value: &[u8]) -> Self {
1968        push_header(self.as_vec_mut(), 17u16, value.len() as u16);
1969        self.as_vec_mut().extend(value);
1970        self
1971    }
1972    pub fn push_via(mut self, value: &[u8]) -> Self {
1973        push_header(self.as_vec_mut(), 18u16, value.len() as u16);
1974        self.as_vec_mut().extend(value);
1975        self
1976    }
1977    pub fn push_newdst(mut self, value: &[u8]) -> Self {
1978        push_header(self.as_vec_mut(), 19u16, value.len() as u16);
1979        self.as_vec_mut().extend(value);
1980        self
1981    }
1982    pub fn push_pref(mut self, value: u8) -> Self {
1983        push_header(self.as_vec_mut(), 20u16, 1 as u16);
1984        self.as_vec_mut().extend(value.to_ne_bytes());
1985        self
1986    }
1987    pub fn push_encap_type(mut self, value: u16) -> Self {
1988        push_header(self.as_vec_mut(), 21u16, 2 as u16);
1989        self.as_vec_mut().extend(value.to_ne_bytes());
1990        self
1991    }
1992    pub fn push_encap(mut self, value: &[u8]) -> Self {
1993        push_header(self.as_vec_mut(), 22u16, value.len() as u16);
1994        self.as_vec_mut().extend(value);
1995        self
1996    }
1997    pub fn push_expires(mut self, value: u32) -> Self {
1998        push_header(self.as_vec_mut(), 23u16, 4 as u16);
1999        self.as_vec_mut().extend(value.to_ne_bytes());
2000        self
2001    }
2002    pub fn push_pad(mut self, value: &[u8]) -> Self {
2003        push_header(self.as_vec_mut(), 24u16, value.len() as u16);
2004        self.as_vec_mut().extend(value);
2005        self
2006    }
2007    pub fn push_uid(mut self, value: u32) -> Self {
2008        push_header(self.as_vec_mut(), 25u16, 4 as u16);
2009        self.as_vec_mut().extend(value.to_ne_bytes());
2010        self
2011    }
2012    pub fn push_ttl_propagate(mut self, value: u8) -> Self {
2013        push_header(self.as_vec_mut(), 26u16, 1 as u16);
2014        self.as_vec_mut().extend(value.to_ne_bytes());
2015        self
2016    }
2017    pub fn push_ip_proto(mut self, value: u8) -> Self {
2018        push_header(self.as_vec_mut(), 27u16, 1 as u16);
2019        self.as_vec_mut().extend(value.to_ne_bytes());
2020        self
2021    }
2022    pub fn push_sport(mut self, value: u16) -> Self {
2023        push_header(self.as_vec_mut(), 28u16, 2 as u16);
2024        self.as_vec_mut().extend(value.to_ne_bytes());
2025        self
2026    }
2027    pub fn push_dport(mut self, value: u16) -> Self {
2028        push_header(self.as_vec_mut(), 29u16, 2 as u16);
2029        self.as_vec_mut().extend(value.to_ne_bytes());
2030        self
2031    }
2032    pub fn push_nh_id(mut self, value: u32) -> Self {
2033        push_header(self.as_vec_mut(), 30u16, 4 as u16);
2034        self.as_vec_mut().extend(value.to_ne_bytes());
2035        self
2036    }
2037    pub fn push_flowlabel(mut self, value: u32) -> Self {
2038        push_header(self.as_vec_mut(), 31u16, 4 as u16);
2039        self.as_vec_mut().extend(value.to_be_bytes());
2040        self
2041    }
2042}
2043impl<Prev: Pusher> Drop for PushRouteAttrs<Prev> {
2044    fn drop(&mut self) {
2045        if let Some(prev) = &mut self.prev {
2046            if let Some(header_offset) = &self.header_offset {
2047                finalize_nested_header(prev.as_vec_mut(), *header_offset);
2048            }
2049        }
2050    }
2051}
2052pub struct PushMetrics<Prev: Pusher> {
2053    pub(crate) prev: Option<Prev>,
2054    pub(crate) header_offset: Option<usize>,
2055}
2056impl<Prev: Pusher> Pusher for PushMetrics<Prev> {
2057    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
2058        self.prev.as_mut().unwrap().as_vec_mut()
2059    }
2060    fn as_vec(&self) -> &Vec<u8> {
2061        self.prev.as_ref().unwrap().as_vec()
2062    }
2063}
2064impl<Prev: Pusher> PushMetrics<Prev> {
2065    pub fn new(prev: Prev) -> Self {
2066        Self {
2067            prev: Some(prev),
2068            header_offset: None,
2069        }
2070    }
2071    pub fn end_nested(mut self) -> Prev {
2072        let mut prev = self.prev.take().unwrap();
2073        if let Some(header_offset) = &self.header_offset {
2074            finalize_nested_header(prev.as_vec_mut(), *header_offset);
2075        }
2076        prev
2077    }
2078    pub fn push_lock(mut self, value: u32) -> Self {
2079        push_header(self.as_vec_mut(), 1u16, 4 as u16);
2080        self.as_vec_mut().extend(value.to_ne_bytes());
2081        self
2082    }
2083    pub fn push_mtu(mut self, value: u32) -> Self {
2084        push_header(self.as_vec_mut(), 2u16, 4 as u16);
2085        self.as_vec_mut().extend(value.to_ne_bytes());
2086        self
2087    }
2088    pub fn push_window(mut self, value: u32) -> Self {
2089        push_header(self.as_vec_mut(), 3u16, 4 as u16);
2090        self.as_vec_mut().extend(value.to_ne_bytes());
2091        self
2092    }
2093    pub fn push_rtt(mut self, value: u32) -> Self {
2094        push_header(self.as_vec_mut(), 4u16, 4 as u16);
2095        self.as_vec_mut().extend(value.to_ne_bytes());
2096        self
2097    }
2098    pub fn push_rttvar(mut self, value: u32) -> Self {
2099        push_header(self.as_vec_mut(), 5u16, 4 as u16);
2100        self.as_vec_mut().extend(value.to_ne_bytes());
2101        self
2102    }
2103    pub fn push_ssthresh(mut self, value: u32) -> Self {
2104        push_header(self.as_vec_mut(), 6u16, 4 as u16);
2105        self.as_vec_mut().extend(value.to_ne_bytes());
2106        self
2107    }
2108    pub fn push_cwnd(mut self, value: u32) -> Self {
2109        push_header(self.as_vec_mut(), 7u16, 4 as u16);
2110        self.as_vec_mut().extend(value.to_ne_bytes());
2111        self
2112    }
2113    pub fn push_advmss(mut self, value: u32) -> Self {
2114        push_header(self.as_vec_mut(), 8u16, 4 as u16);
2115        self.as_vec_mut().extend(value.to_ne_bytes());
2116        self
2117    }
2118    pub fn push_reordering(mut self, value: u32) -> Self {
2119        push_header(self.as_vec_mut(), 9u16, 4 as u16);
2120        self.as_vec_mut().extend(value.to_ne_bytes());
2121        self
2122    }
2123    pub fn push_hoplimit(mut self, value: u32) -> Self {
2124        push_header(self.as_vec_mut(), 10u16, 4 as u16);
2125        self.as_vec_mut().extend(value.to_ne_bytes());
2126        self
2127    }
2128    pub fn push_initcwnd(mut self, value: u32) -> Self {
2129        push_header(self.as_vec_mut(), 11u16, 4 as u16);
2130        self.as_vec_mut().extend(value.to_ne_bytes());
2131        self
2132    }
2133    pub fn push_features(mut self, value: u32) -> Self {
2134        push_header(self.as_vec_mut(), 12u16, 4 as u16);
2135        self.as_vec_mut().extend(value.to_ne_bytes());
2136        self
2137    }
2138    pub fn push_rto_min(mut self, value: u32) -> Self {
2139        push_header(self.as_vec_mut(), 13u16, 4 as u16);
2140        self.as_vec_mut().extend(value.to_ne_bytes());
2141        self
2142    }
2143    pub fn push_initrwnd(mut self, value: u32) -> Self {
2144        push_header(self.as_vec_mut(), 14u16, 4 as u16);
2145        self.as_vec_mut().extend(value.to_ne_bytes());
2146        self
2147    }
2148    pub fn push_quickack(mut self, value: u32) -> Self {
2149        push_header(self.as_vec_mut(), 15u16, 4 as u16);
2150        self.as_vec_mut().extend(value.to_ne_bytes());
2151        self
2152    }
2153    pub fn push_cc_algo(mut self, value: &CStr) -> Self {
2154        push_header(
2155            self.as_vec_mut(),
2156            16u16,
2157            value.to_bytes_with_nul().len() as u16,
2158        );
2159        self.as_vec_mut().extend(value.to_bytes_with_nul());
2160        self
2161    }
2162    pub fn push_cc_algo_bytes(mut self, value: &[u8]) -> Self {
2163        push_header(self.as_vec_mut(), 16u16, (value.len() + 1) as u16);
2164        self.as_vec_mut().extend(value);
2165        self.as_vec_mut().push(0);
2166        self
2167    }
2168    pub fn push_fastopen_no_cookie(mut self, value: u32) -> Self {
2169        push_header(self.as_vec_mut(), 17u16, 4 as u16);
2170        self.as_vec_mut().extend(value.to_ne_bytes());
2171        self
2172    }
2173}
2174impl<Prev: Pusher> Drop for PushMetrics<Prev> {
2175    fn drop(&mut self) {
2176        if let Some(prev) = &mut self.prev {
2177            if let Some(header_offset) = &self.header_offset {
2178                finalize_nested_header(prev.as_vec_mut(), *header_offset);
2179            }
2180        }
2181    }
2182}
2183#[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\n"]
2184#[derive(Debug)]
2185pub struct OpGetrouteDump<'r> {
2186    request: Request<'r>,
2187}
2188impl<'r> OpGetrouteDump<'r> {
2189    pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2190        Self::write_header(request.buf_mut(), header);
2191        Self {
2192            request: request.set_dump(),
2193        }
2194    }
2195    pub fn encode_request<'buf>(
2196        buf: &'buf mut Vec<u8>,
2197        header: &Rtmsg,
2198    ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2199        Self::write_header(buf, header);
2200        PushRouteAttrs::new(buf)
2201    }
2202    pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2203        PushRouteAttrs::new(self.request.buf_mut())
2204    }
2205    pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2206        PushRouteAttrs::new(self.request.buf)
2207    }
2208    pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2209        let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2210        (
2211            Rtmsg::new_from_slice(header).unwrap_or_default(),
2212            IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2213        )
2214    }
2215    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Rtmsg) {
2216        prev.as_vec_mut().extend(header.as_slice());
2217    }
2218}
2219impl NetlinkRequest for OpGetrouteDump<'_> {
2220    fn protocol(&self) -> Protocol {
2221        Protocol::Raw {
2222            protonum: 0u16,
2223            request_type: 26u16,
2224        }
2225    }
2226    fn flags(&self) -> u16 {
2227        self.request.flags
2228    }
2229    fn payload(&self) -> &[u8] {
2230        self.request.buf()
2231    }
2232    type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2233    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2234        Self::decode_request(buf)
2235    }
2236    fn lookup(
2237        buf: &[u8],
2238        offset: usize,
2239        missing_type: Option<u16>,
2240    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2241        Self::decode_request(buf)
2242            .1
2243            .lookup_attr(offset, missing_type)
2244    }
2245}
2246#[doc = "Dump route information.\n\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\n"]
2247#[derive(Debug)]
2248pub struct OpGetrouteDo<'r> {
2249    request: Request<'r>,
2250}
2251impl<'r> OpGetrouteDo<'r> {
2252    pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2253        Self::write_header(request.buf_mut(), header);
2254        Self { request: request }
2255    }
2256    pub fn encode_request<'buf>(
2257        buf: &'buf mut Vec<u8>,
2258        header: &Rtmsg,
2259    ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2260        Self::write_header(buf, header);
2261        PushRouteAttrs::new(buf)
2262    }
2263    pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2264        PushRouteAttrs::new(self.request.buf_mut())
2265    }
2266    pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2267        PushRouteAttrs::new(self.request.buf)
2268    }
2269    pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2270        let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2271        (
2272            Rtmsg::new_from_slice(header).unwrap_or_default(),
2273            IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2274        )
2275    }
2276    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Rtmsg) {
2277        prev.as_vec_mut().extend(header.as_slice());
2278    }
2279}
2280impl NetlinkRequest for OpGetrouteDo<'_> {
2281    fn protocol(&self) -> Protocol {
2282        Protocol::Raw {
2283            protonum: 0u16,
2284            request_type: 26u16,
2285        }
2286    }
2287    fn flags(&self) -> u16 {
2288        self.request.flags
2289    }
2290    fn payload(&self) -> &[u8] {
2291        self.request.buf()
2292    }
2293    type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2294    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2295        Self::decode_request(buf)
2296    }
2297    fn lookup(
2298        buf: &[u8],
2299        offset: usize,
2300        missing_type: Option<u16>,
2301    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2302        Self::decode_request(buf)
2303            .1
2304            .lookup_attr(offset, missing_type)
2305    }
2306}
2307#[doc = "Create a new route\n\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\n"]
2308#[derive(Debug)]
2309pub struct OpNewrouteDo<'r> {
2310    request: Request<'r>,
2311}
2312impl<'r> OpNewrouteDo<'r> {
2313    pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2314        Self::write_header(request.buf_mut(), header);
2315        Self { request: request }
2316    }
2317    pub fn encode_request<'buf>(
2318        buf: &'buf mut Vec<u8>,
2319        header: &Rtmsg,
2320    ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2321        Self::write_header(buf, header);
2322        PushRouteAttrs::new(buf)
2323    }
2324    pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2325        PushRouteAttrs::new(self.request.buf_mut())
2326    }
2327    pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2328        PushRouteAttrs::new(self.request.buf)
2329    }
2330    pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2331        let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2332        (
2333            Rtmsg::new_from_slice(header).unwrap_or_default(),
2334            IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2335        )
2336    }
2337    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Rtmsg) {
2338        prev.as_vec_mut().extend(header.as_slice());
2339    }
2340}
2341impl NetlinkRequest for OpNewrouteDo<'_> {
2342    fn protocol(&self) -> Protocol {
2343        Protocol::Raw {
2344            protonum: 0u16,
2345            request_type: 24u16,
2346        }
2347    }
2348    fn flags(&self) -> u16 {
2349        self.request.flags
2350    }
2351    fn payload(&self) -> &[u8] {
2352        self.request.buf()
2353    }
2354    type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2355    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2356        Self::decode_request(buf)
2357    }
2358    fn lookup(
2359        buf: &[u8],
2360        offset: usize,
2361        missing_type: Option<u16>,
2362    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2363        Self::decode_request(buf)
2364            .1
2365            .lookup_attr(offset, missing_type)
2366    }
2367}
2368#[doc = "Delete an existing route\n\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\n"]
2369#[derive(Debug)]
2370pub struct OpDelrouteDo<'r> {
2371    request: Request<'r>,
2372}
2373impl<'r> OpDelrouteDo<'r> {
2374    pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2375        Self::write_header(request.buf_mut(), header);
2376        Self { request: request }
2377    }
2378    pub fn encode_request<'buf>(
2379        buf: &'buf mut Vec<u8>,
2380        header: &Rtmsg,
2381    ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2382        Self::write_header(buf, header);
2383        PushRouteAttrs::new(buf)
2384    }
2385    pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2386        PushRouteAttrs::new(self.request.buf_mut())
2387    }
2388    pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2389        PushRouteAttrs::new(self.request.buf)
2390    }
2391    pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2392        let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2393        (
2394            Rtmsg::new_from_slice(header).unwrap_or_default(),
2395            IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2396        )
2397    }
2398    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Rtmsg) {
2399        prev.as_vec_mut().extend(header.as_slice());
2400    }
2401}
2402impl NetlinkRequest for OpDelrouteDo<'_> {
2403    fn protocol(&self) -> Protocol {
2404        Protocol::Raw {
2405            protonum: 0u16,
2406            request_type: 25u16,
2407        }
2408    }
2409    fn flags(&self) -> u16 {
2410        self.request.flags
2411    }
2412    fn payload(&self) -> &[u8] {
2413        self.request.buf()
2414    }
2415    type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2416    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2417        Self::decode_request(buf)
2418    }
2419    fn lookup(
2420        buf: &[u8],
2421        offset: usize,
2422        missing_type: Option<u16>,
2423    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2424        Self::decode_request(buf)
2425            .1
2426            .lookup_attr(offset, missing_type)
2427    }
2428}
2429#[derive(Debug)]
2430pub struct ChainedFinal<'a> {
2431    inner: Chained<'a>,
2432}
2433#[derive(Debug)]
2434pub struct Chained<'a> {
2435    buf: RequestBuf<'a>,
2436    first_seq: u32,
2437    lookups: Vec<(&'static str, LookupFn)>,
2438    last_header_offset: usize,
2439    last_kind: Option<RequestInfo>,
2440}
2441impl<'a> ChainedFinal<'a> {
2442    pub fn into_chained(self) -> Chained<'a> {
2443        self.inner
2444    }
2445    pub fn buf(&self) -> &Vec<u8> {
2446        self.inner.buf()
2447    }
2448    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2449        self.inner.buf_mut()
2450    }
2451    fn get_index(&self, seq: u32) -> Option<u32> {
2452        let min = self.inner.first_seq;
2453        let max = min.wrapping_add(self.inner.lookups.len() as u32);
2454        return if min <= max {
2455            (min..max).contains(&seq).then(|| seq - min)
2456        } else if min <= seq {
2457            Some(seq - min)
2458        } else if seq < max {
2459            Some(u32::MAX - min + seq)
2460        } else {
2461            None
2462        };
2463    }
2464}
2465impl crate::traits::NetlinkChained for ChainedFinal<'_> {
2466    fn protonum(&self) -> u16 {
2467        PROTONUM
2468    }
2469    fn payload(&self) -> &[u8] {
2470        self.buf()
2471    }
2472    fn chain_len(&self) -> usize {
2473        self.inner.lookups.len()
2474    }
2475    fn get_index(&self, seq: u32) -> Option<usize> {
2476        self.get_index(seq).map(|n| n as usize)
2477    }
2478    fn name(&self, index: usize) -> &'static str {
2479        self.inner.lookups[index].0
2480    }
2481    fn lookup(&self, index: usize) -> LookupFn {
2482        self.inner.lookups[index].1
2483    }
2484}
2485impl Chained<'static> {
2486    pub fn new(first_seq: u32) -> Self {
2487        Self::new_from_buf(Vec::new(), first_seq)
2488    }
2489    pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
2490        Self {
2491            buf: RequestBuf::Own(buf),
2492            first_seq,
2493            lookups: Vec::new(),
2494            last_header_offset: 0,
2495            last_kind: None,
2496        }
2497    }
2498    pub fn into_buf(self) -> Vec<u8> {
2499        match self.buf {
2500            RequestBuf::Own(buf) => buf,
2501            _ => unreachable!(),
2502        }
2503    }
2504}
2505impl<'a> Chained<'a> {
2506    pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
2507        Self {
2508            buf: RequestBuf::Ref(buf),
2509            first_seq,
2510            lookups: Vec::new(),
2511            last_header_offset: 0,
2512            last_kind: None,
2513        }
2514    }
2515    pub fn finalize(mut self) -> ChainedFinal<'a> {
2516        self.update_header();
2517        ChainedFinal { inner: self }
2518    }
2519    pub fn request(&mut self) -> Request<'_> {
2520        self.update_header();
2521        self.last_header_offset = self.buf().len();
2522        self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
2523        let mut request = Request::new_extend(self.buf.buf_mut());
2524        self.last_kind = None;
2525        request.writeback = Some(&mut self.last_kind);
2526        request
2527    }
2528    pub fn buf(&self) -> &Vec<u8> {
2529        self.buf.buf()
2530    }
2531    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2532        self.buf.buf_mut()
2533    }
2534    fn update_header(&mut self) {
2535        let Some(RequestInfo {
2536            protocol,
2537            flags,
2538            name,
2539            lookup,
2540        }) = self.last_kind
2541        else {
2542            if !self.buf().is_empty() {
2543                assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
2544                self.buf.buf_mut().truncate(self.last_header_offset);
2545            }
2546            return;
2547        };
2548        let header_offset = self.last_header_offset;
2549        let request_type = match protocol {
2550            Protocol::Raw { request_type, .. } => request_type,
2551            Protocol::Generic(_) => unreachable!(),
2552        };
2553        let index = self.lookups.len();
2554        let seq = self.first_seq.wrapping_add(index as u32);
2555        self.lookups.push((name, lookup));
2556        let buf = self.buf_mut();
2557        align(buf);
2558        let header = Nlmsghdr {
2559            len: (buf.len() - header_offset) as u32,
2560            r#type: request_type,
2561            flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
2562            seq,
2563            pid: 0,
2564        };
2565        buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
2566    }
2567}
2568use crate::traits::LookupFn;
2569use crate::utils::RequestBuf;
2570#[derive(Debug)]
2571pub struct Request<'buf> {
2572    buf: RequestBuf<'buf>,
2573    flags: u16,
2574    writeback: Option<&'buf mut Option<RequestInfo>>,
2575}
2576#[allow(unused)]
2577#[derive(Debug, Clone)]
2578pub struct RequestInfo {
2579    protocol: Protocol,
2580    flags: u16,
2581    name: &'static str,
2582    lookup: LookupFn,
2583}
2584impl Request<'static> {
2585    pub fn new() -> Self {
2586        Self::new_from_buf(Vec::new())
2587    }
2588    pub fn new_from_buf(buf: Vec<u8>) -> Self {
2589        Self {
2590            flags: 0,
2591            buf: RequestBuf::Own(buf),
2592            writeback: None,
2593        }
2594    }
2595    pub fn into_buf(self) -> Vec<u8> {
2596        match self.buf {
2597            RequestBuf::Own(buf) => buf,
2598            _ => unreachable!(),
2599        }
2600    }
2601}
2602impl<'buf> Request<'buf> {
2603    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
2604        buf.clear();
2605        Self::new_extend(buf)
2606    }
2607    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
2608        Self {
2609            flags: 0,
2610            buf: RequestBuf::Ref(buf),
2611            writeback: None,
2612        }
2613    }
2614    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
2615        let Some(writeback) = &mut self.writeback else {
2616            return;
2617        };
2618        **writeback = Some(RequestInfo {
2619            protocol,
2620            flags: self.flags,
2621            name,
2622            lookup,
2623        })
2624    }
2625    pub fn buf(&self) -> &Vec<u8> {
2626        self.buf.buf()
2627    }
2628    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2629        self.buf.buf_mut()
2630    }
2631    #[doc = "Set `NLM_F_CREATE` flag"]
2632    pub fn set_create(mut self) -> Self {
2633        self.flags |= consts::NLM_F_CREATE as u16;
2634        self
2635    }
2636    #[doc = "Set `NLM_F_EXCL` flag"]
2637    pub fn set_excl(mut self) -> Self {
2638        self.flags |= consts::NLM_F_EXCL as u16;
2639        self
2640    }
2641    #[doc = "Set `NLM_F_REPLACE` flag"]
2642    pub fn set_replace(mut self) -> Self {
2643        self.flags |= consts::NLM_F_REPLACE as u16;
2644        self
2645    }
2646    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
2647    pub fn set_change(self) -> Self {
2648        self.set_create().set_replace()
2649    }
2650    #[doc = "Set `NLM_F_APPEND` flag"]
2651    pub fn set_append(mut self) -> Self {
2652        self.flags |= consts::NLM_F_APPEND as u16;
2653        self
2654    }
2655    #[doc = "Set `self.flags |= flags`"]
2656    pub fn set_flags(mut self, flags: u16) -> Self {
2657        self.flags |= flags;
2658        self
2659    }
2660    #[doc = "Set `self.flags ^= self.flags & flags`"]
2661    pub fn unset_flags(mut self, flags: u16) -> Self {
2662        self.flags ^= self.flags & flags;
2663        self
2664    }
2665    #[doc = "Set `NLM_F_DUMP` flag"]
2666    fn set_dump(mut self) -> Self {
2667        self.flags |= consts::NLM_F_DUMP as u16;
2668        self
2669    }
2670    #[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\n"]
2671    pub fn op_getroute_dump(self, header: &Rtmsg) -> OpGetrouteDump<'buf> {
2672        let mut res = OpGetrouteDump::new(self, header);
2673        res.request
2674            .do_writeback(res.protocol(), "op-getroute-dump", OpGetrouteDump::lookup);
2675        res
2676    }
2677    #[doc = "Dump route information.\n\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\n"]
2678    pub fn op_getroute_do(self, header: &Rtmsg) -> OpGetrouteDo<'buf> {
2679        let mut res = OpGetrouteDo::new(self, header);
2680        res.request
2681            .do_writeback(res.protocol(), "op-getroute-do", OpGetrouteDo::lookup);
2682        res
2683    }
2684    #[doc = "Create a new route\n\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\n"]
2685    pub fn op_newroute_do(self, header: &Rtmsg) -> OpNewrouteDo<'buf> {
2686        let mut res = OpNewrouteDo::new(self, header);
2687        res.request
2688            .do_writeback(res.protocol(), "op-newroute-do", OpNewrouteDo::lookup);
2689        res
2690    }
2691    #[doc = "Delete an existing route\n\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\n"]
2692    pub fn op_delroute_do(self, header: &Rtmsg) -> OpDelrouteDo<'buf> {
2693        let mut res = OpDelrouteDo::new(self, header);
2694        res.request
2695            .do_writeback(res.protocol(), "op-delroute-do", OpDelrouteDo::lookup);
2696        res
2697    }
2698}
2699#[cfg(test)]
2700mod generated_tests {
2701    use super::*;
2702    #[test]
2703    fn tests() {
2704        let _ = IterableRouteAttrs::get_cacheinfo;
2705        let _ = IterableRouteAttrs::get_dport;
2706        let _ = IterableRouteAttrs::get_dst;
2707        let _ = IterableRouteAttrs::get_encap;
2708        let _ = IterableRouteAttrs::get_encap_type;
2709        let _ = IterableRouteAttrs::get_expires;
2710        let _ = IterableRouteAttrs::get_flow;
2711        let _ = IterableRouteAttrs::get_flowlabel;
2712        let _ = IterableRouteAttrs::get_gateway;
2713        let _ = IterableRouteAttrs::get_iif;
2714        let _ = IterableRouteAttrs::get_ip_proto;
2715        let _ = IterableRouteAttrs::get_mark;
2716        let _ = IterableRouteAttrs::get_metrics;
2717        let _ = IterableRouteAttrs::get_mfc_stats;
2718        let _ = IterableRouteAttrs::get_multipath;
2719        let _ = IterableRouteAttrs::get_newdst;
2720        let _ = IterableRouteAttrs::get_nh_id;
2721        let _ = IterableRouteAttrs::get_oif;
2722        let _ = IterableRouteAttrs::get_pad;
2723        let _ = IterableRouteAttrs::get_pref;
2724        let _ = IterableRouteAttrs::get_prefsrc;
2725        let _ = IterableRouteAttrs::get_priority;
2726        let _ = IterableRouteAttrs::get_sport;
2727        let _ = IterableRouteAttrs::get_src;
2728        let _ = IterableRouteAttrs::get_table;
2729        let _ = IterableRouteAttrs::get_ttl_propagate;
2730        let _ = IterableRouteAttrs::get_uid;
2731        let _ = IterableRouteAttrs::get_via;
2732        let _ = PushRouteAttrs::<&mut Vec<u8>>::nested_metrics;
2733        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_cacheinfo;
2734        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_dport;
2735        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_dst;
2736        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_encap;
2737        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_encap_type;
2738        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_expires;
2739        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_flow;
2740        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_flowlabel;
2741        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_gateway;
2742        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_iif;
2743        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_ip_proto;
2744        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_mark;
2745        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_mfc_stats;
2746        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_multipath;
2747        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_newdst;
2748        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_nh_id;
2749        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_oif;
2750        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_pad;
2751        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_pref;
2752        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_prefsrc;
2753        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_priority;
2754        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_sport;
2755        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_src;
2756        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_table;
2757        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_ttl_propagate;
2758        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_uid;
2759        let _ = PushRouteAttrs::<&mut Vec<u8>>::push_via;
2760    }
2761}