Skip to main content

netlink_bindings/rt-neigh/
mod.rs

1#![doc = "IP neighbour management over rtnetlink\\."]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "rt-neigh";
17pub const PROTONAME_CSTR: &CStr = c"rt-neigh";
18pub const PROTONUM: u16 = 0u16;
19#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
20#[derive(Debug, Clone, Copy)]
21pub enum NudState {
22    Incomplete = 1 << 0,
23    Reachable = 1 << 1,
24    Stale = 1 << 2,
25    Delay = 1 << 3,
26    Probe = 1 << 4,
27    Failed = 1 << 5,
28    Noarp = 1 << 6,
29    Permanent = 1 << 7,
30}
31impl NudState {
32    pub fn from_value(value: u64) -> Option<Self> {
33        Some(match value {
34            n if n == 1 << 0 => Self::Incomplete,
35            n if n == 1 << 1 => Self::Reachable,
36            n if n == 1 << 2 => Self::Stale,
37            n if n == 1 << 3 => Self::Delay,
38            n if n == 1 << 4 => Self::Probe,
39            n if n == 1 << 5 => Self::Failed,
40            n if n == 1 << 6 => Self::Noarp,
41            n if n == 1 << 7 => Self::Permanent,
42            _ => return None,
43        })
44    }
45}
46#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
47#[derive(Debug, Clone, Copy)]
48pub enum NtfFlags {
49    Use = 1 << 0,
50    _Self = 1 << 1,
51    Master = 1 << 2,
52    Proxy = 1 << 3,
53    ExtLearned = 1 << 4,
54    Offloaded = 1 << 5,
55    Sticky = 1 << 6,
56    Router = 1 << 7,
57}
58impl NtfFlags {
59    pub fn from_value(value: u64) -> Option<Self> {
60        Some(match value {
61            n if n == 1 << 0 => Self::Use,
62            n if n == 1 << 1 => Self::_Self,
63            n if n == 1 << 2 => Self::Master,
64            n if n == 1 << 3 => Self::Proxy,
65            n if n == 1 << 4 => Self::ExtLearned,
66            n if n == 1 << 5 => Self::Offloaded,
67            n if n == 1 << 6 => Self::Sticky,
68            n if n == 1 << 7 => Self::Router,
69            _ => return None,
70        })
71    }
72}
73#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
74#[derive(Debug, Clone, Copy)]
75pub enum NtfExtFlags {
76    Managed = 1 << 0,
77    Locked = 1 << 1,
78    ExtValidated = 1 << 2,
79}
80impl NtfExtFlags {
81    pub fn from_value(value: u64) -> Option<Self> {
82        Some(match value {
83            n if n == 1 << 0 => Self::Managed,
84            n if n == 1 << 1 => Self::Locked,
85            n if n == 1 << 2 => Self::ExtValidated,
86            _ => return None,
87        })
88    }
89}
90#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
91#[derive(Debug, Clone, Copy)]
92pub enum RtmType {
93    Unspec = 0,
94    Unicast = 1,
95    Local = 2,
96    Broadcast = 3,
97    Anycast = 4,
98    Multicast = 5,
99    Blackhole = 6,
100    Unreachable = 7,
101    Prohibit = 8,
102    Throw = 9,
103    Nat = 10,
104    Xresolve = 11,
105}
106impl RtmType {
107    pub fn from_value(value: u64) -> Option<Self> {
108        Some(match value {
109            0 => Self::Unspec,
110            1 => Self::Unicast,
111            2 => Self::Local,
112            3 => Self::Broadcast,
113            4 => Self::Anycast,
114            5 => Self::Multicast,
115            6 => Self::Blackhole,
116            7 => Self::Unreachable,
117            8 => Self::Prohibit,
118            9 => Self::Throw,
119            10 => Self::Nat,
120            11 => Self::Xresolve,
121            _ => return None,
122        })
123    }
124}
125#[repr(C, packed(4))]
126pub struct Ndmsg {
127    pub ndm_family: u8,
128    pub _ndm_pad: [u8; 3usize],
129    pub ndm_ifindex: i32,
130    #[doc = "Associated type: [`NudState`] (enum)"]
131    pub ndm_state: u16,
132    #[doc = "Associated type: [`NtfFlags`] (enum)"]
133    pub ndm_flags: u8,
134    #[doc = "Associated type: [`RtmType`] (enum)"]
135    pub ndm_type: u8,
136}
137impl Clone for Ndmsg {
138    fn clone(&self) -> Self {
139        Self::new_from_array(*self.as_array())
140    }
141}
142#[doc = "Create zero-initialized struct"]
143impl Default for Ndmsg {
144    fn default() -> Self {
145        Self::new()
146    }
147}
148impl Ndmsg {
149    #[doc = "Create zero-initialized struct"]
150    pub fn new() -> Self {
151        Self::new_from_array([0u8; Self::len()])
152    }
153    #[doc = "Copy from contents from slice"]
154    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
155        if other.len() != Self::len() {
156            return None;
157        }
158        let mut buf = [0u8; Self::len()];
159        buf.clone_from_slice(other);
160        Some(Self::new_from_array(buf))
161    }
162    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
163    pub fn new_from_zeroed(other: &[u8]) -> Self {
164        let mut buf = [0u8; Self::len()];
165        let len = buf.len().min(other.len());
166        buf[..len].clone_from_slice(&other[..len]);
167        Self::new_from_array(buf)
168    }
169    pub fn new_from_array(buf: [u8; 12usize]) -> Self {
170        unsafe { std::mem::transmute(buf) }
171    }
172    pub fn as_slice(&self) -> &[u8] {
173        unsafe {
174            let ptr: *const u8 = std::mem::transmute(self as *const Self);
175            std::slice::from_raw_parts(ptr, Self::len())
176        }
177    }
178    pub fn from_slice(buf: &[u8]) -> &Self {
179        assert!(buf.len() >= Self::len());
180        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
181        unsafe { std::mem::transmute(buf.as_ptr()) }
182    }
183    pub fn as_array(&self) -> &[u8; 12usize] {
184        unsafe { std::mem::transmute(self) }
185    }
186    pub fn from_array(buf: &[u8; 12usize]) -> &Self {
187        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
188        unsafe { std::mem::transmute(buf) }
189    }
190    pub fn into_array(self) -> [u8; 12usize] {
191        unsafe { std::mem::transmute(self) }
192    }
193    pub const fn len() -> usize {
194        const _: () = assert!(std::mem::size_of::<Ndmsg>() == 12usize);
195        12usize
196    }
197}
198impl std::fmt::Debug for Ndmsg {
199    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200        fmt.debug_struct("Ndmsg")
201            .field("ndm_family", &self.ndm_family)
202            .field("ndm_ifindex", &self.ndm_ifindex)
203            .field(
204                "ndm_state",
205                &FormatFlags(self.ndm_state.into(), NudState::from_value),
206            )
207            .field(
208                "ndm_flags",
209                &FormatFlags(self.ndm_flags.into(), NtfFlags::from_value),
210            )
211            .field(
212                "ndm_type",
213                &FormatEnum(self.ndm_type.into(), RtmType::from_value),
214            )
215            .finish()
216    }
217}
218#[repr(C, packed(4))]
219pub struct Ndtmsg {
220    pub family: u8,
221    pub _pad: [u8; 3usize],
222}
223impl Clone for Ndtmsg {
224    fn clone(&self) -> Self {
225        Self::new_from_array(*self.as_array())
226    }
227}
228#[doc = "Create zero-initialized struct"]
229impl Default for Ndtmsg {
230    fn default() -> Self {
231        Self::new()
232    }
233}
234impl Ndtmsg {
235    #[doc = "Create zero-initialized struct"]
236    pub fn new() -> Self {
237        Self::new_from_array([0u8; Self::len()])
238    }
239    #[doc = "Copy from contents from slice"]
240    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
241        if other.len() != Self::len() {
242            return None;
243        }
244        let mut buf = [0u8; Self::len()];
245        buf.clone_from_slice(other);
246        Some(Self::new_from_array(buf))
247    }
248    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
249    pub fn new_from_zeroed(other: &[u8]) -> Self {
250        let mut buf = [0u8; Self::len()];
251        let len = buf.len().min(other.len());
252        buf[..len].clone_from_slice(&other[..len]);
253        Self::new_from_array(buf)
254    }
255    pub fn new_from_array(buf: [u8; 4usize]) -> Self {
256        unsafe { std::mem::transmute(buf) }
257    }
258    pub fn as_slice(&self) -> &[u8] {
259        unsafe {
260            let ptr: *const u8 = std::mem::transmute(self as *const Self);
261            std::slice::from_raw_parts(ptr, Self::len())
262        }
263    }
264    pub fn from_slice(buf: &[u8]) -> &Self {
265        assert!(buf.len() >= Self::len());
266        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
267        unsafe { std::mem::transmute(buf.as_ptr()) }
268    }
269    pub fn as_array(&self) -> &[u8; 4usize] {
270        unsafe { std::mem::transmute(self) }
271    }
272    pub fn from_array(buf: &[u8; 4usize]) -> &Self {
273        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
274        unsafe { std::mem::transmute(buf) }
275    }
276    pub fn into_array(self) -> [u8; 4usize] {
277        unsafe { std::mem::transmute(self) }
278    }
279    pub const fn len() -> usize {
280        const _: () = assert!(std::mem::size_of::<Ndtmsg>() == 4usize);
281        4usize
282    }
283}
284impl std::fmt::Debug for Ndtmsg {
285    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286        fmt.debug_struct("Ndtmsg")
287            .field("family", &self.family)
288            .finish()
289    }
290}
291#[derive(Debug)]
292#[repr(C, packed(4))]
293pub struct NdaCacheinfo {
294    pub confirmed: u32,
295    pub used: u32,
296    pub updated: u32,
297    pub refcnt: u32,
298}
299impl Clone for NdaCacheinfo {
300    fn clone(&self) -> Self {
301        Self::new_from_array(*self.as_array())
302    }
303}
304#[doc = "Create zero-initialized struct"]
305impl Default for NdaCacheinfo {
306    fn default() -> Self {
307        Self::new()
308    }
309}
310impl NdaCacheinfo {
311    #[doc = "Create zero-initialized struct"]
312    pub fn new() -> Self {
313        Self::new_from_array([0u8; Self::len()])
314    }
315    #[doc = "Copy from contents from slice"]
316    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
317        if other.len() != Self::len() {
318            return None;
319        }
320        let mut buf = [0u8; Self::len()];
321        buf.clone_from_slice(other);
322        Some(Self::new_from_array(buf))
323    }
324    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
325    pub fn new_from_zeroed(other: &[u8]) -> Self {
326        let mut buf = [0u8; Self::len()];
327        let len = buf.len().min(other.len());
328        buf[..len].clone_from_slice(&other[..len]);
329        Self::new_from_array(buf)
330    }
331    pub fn new_from_array(buf: [u8; 16usize]) -> Self {
332        unsafe { std::mem::transmute(buf) }
333    }
334    pub fn as_slice(&self) -> &[u8] {
335        unsafe {
336            let ptr: *const u8 = std::mem::transmute(self as *const Self);
337            std::slice::from_raw_parts(ptr, Self::len())
338        }
339    }
340    pub fn from_slice(buf: &[u8]) -> &Self {
341        assert!(buf.len() >= Self::len());
342        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
343        unsafe { std::mem::transmute(buf.as_ptr()) }
344    }
345    pub fn as_array(&self) -> &[u8; 16usize] {
346        unsafe { std::mem::transmute(self) }
347    }
348    pub fn from_array(buf: &[u8; 16usize]) -> &Self {
349        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
350        unsafe { std::mem::transmute(buf) }
351    }
352    pub fn into_array(self) -> [u8; 16usize] {
353        unsafe { std::mem::transmute(self) }
354    }
355    pub const fn len() -> usize {
356        const _: () = assert!(std::mem::size_of::<NdaCacheinfo>() == 16usize);
357        16usize
358    }
359}
360#[derive(Debug)]
361#[repr(C, packed(4))]
362pub struct NdtConfig {
363    pub key_len: u16,
364    pub entry_size: u16,
365    pub entries: u32,
366    pub last_flush: u32,
367    pub last_rand: u32,
368    pub hash_rnd: u32,
369    pub hash_mask: u32,
370    pub hash_chain_gc: u32,
371    pub proxy_qlen: u32,
372}
373impl Clone for NdtConfig {
374    fn clone(&self) -> Self {
375        Self::new_from_array(*self.as_array())
376    }
377}
378#[doc = "Create zero-initialized struct"]
379impl Default for NdtConfig {
380    fn default() -> Self {
381        Self::new()
382    }
383}
384impl NdtConfig {
385    #[doc = "Create zero-initialized struct"]
386    pub fn new() -> Self {
387        Self::new_from_array([0u8; Self::len()])
388    }
389    #[doc = "Copy from contents from slice"]
390    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
391        if other.len() != Self::len() {
392            return None;
393        }
394        let mut buf = [0u8; Self::len()];
395        buf.clone_from_slice(other);
396        Some(Self::new_from_array(buf))
397    }
398    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
399    pub fn new_from_zeroed(other: &[u8]) -> Self {
400        let mut buf = [0u8; Self::len()];
401        let len = buf.len().min(other.len());
402        buf[..len].clone_from_slice(&other[..len]);
403        Self::new_from_array(buf)
404    }
405    pub fn new_from_array(buf: [u8; 32usize]) -> Self {
406        unsafe { std::mem::transmute(buf) }
407    }
408    pub fn as_slice(&self) -> &[u8] {
409        unsafe {
410            let ptr: *const u8 = std::mem::transmute(self as *const Self);
411            std::slice::from_raw_parts(ptr, Self::len())
412        }
413    }
414    pub fn from_slice(buf: &[u8]) -> &Self {
415        assert!(buf.len() >= Self::len());
416        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
417        unsafe { std::mem::transmute(buf.as_ptr()) }
418    }
419    pub fn as_array(&self) -> &[u8; 32usize] {
420        unsafe { std::mem::transmute(self) }
421    }
422    pub fn from_array(buf: &[u8; 32usize]) -> &Self {
423        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
424        unsafe { std::mem::transmute(buf) }
425    }
426    pub fn into_array(self) -> [u8; 32usize] {
427        unsafe { std::mem::transmute(self) }
428    }
429    pub const fn len() -> usize {
430        const _: () = assert!(std::mem::size_of::<NdtConfig>() == 32usize);
431        32usize
432    }
433}
434#[repr(C, packed(4))]
435pub struct NdtStats {
436    pub allocs: u64,
437    pub destroys: u64,
438    pub hash_grows: u64,
439    pub res_failed: u64,
440    pub lookups: u64,
441    pub hits: u64,
442    pub rcv_probes_mcast: u64,
443    pub rcv_probes_ucast: u64,
444    pub periodic_gc_runs: u64,
445    pub forced_gc_runs: u64,
446    pub table_fulls: u64,
447}
448impl Clone for NdtStats {
449    fn clone(&self) -> Self {
450        Self::new_from_array(*self.as_array())
451    }
452}
453#[doc = "Create zero-initialized struct"]
454impl Default for NdtStats {
455    fn default() -> Self {
456        Self::new()
457    }
458}
459impl NdtStats {
460    #[doc = "Create zero-initialized struct"]
461    pub fn new() -> Self {
462        Self::new_from_array([0u8; Self::len()])
463    }
464    #[doc = "Copy from contents from slice"]
465    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
466        if other.len() != Self::len() {
467            return None;
468        }
469        let mut buf = [0u8; Self::len()];
470        buf.clone_from_slice(other);
471        Some(Self::new_from_array(buf))
472    }
473    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
474    pub fn new_from_zeroed(other: &[u8]) -> Self {
475        let mut buf = [0u8; Self::len()];
476        let len = buf.len().min(other.len());
477        buf[..len].clone_from_slice(&other[..len]);
478        Self::new_from_array(buf)
479    }
480    pub fn new_from_array(buf: [u8; 88usize]) -> Self {
481        unsafe { std::mem::transmute(buf) }
482    }
483    pub fn as_slice(&self) -> &[u8] {
484        unsafe {
485            let ptr: *const u8 = std::mem::transmute(self as *const Self);
486            std::slice::from_raw_parts(ptr, Self::len())
487        }
488    }
489    pub fn from_slice(buf: &[u8]) -> &Self {
490        assert!(buf.len() >= Self::len());
491        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
492        unsafe { std::mem::transmute(buf.as_ptr()) }
493    }
494    pub fn as_array(&self) -> &[u8; 88usize] {
495        unsafe { std::mem::transmute(self) }
496    }
497    pub fn from_array(buf: &[u8; 88usize]) -> &Self {
498        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
499        unsafe { std::mem::transmute(buf) }
500    }
501    pub fn into_array(self) -> [u8; 88usize] {
502        unsafe { std::mem::transmute(self) }
503    }
504    pub const fn len() -> usize {
505        const _: () = assert!(std::mem::size_of::<NdtStats>() == 88usize);
506        88usize
507    }
508}
509impl std::fmt::Debug for NdtStats {
510    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
511        fmt.debug_struct("NdtStats")
512            .field("allocs", &{ self.allocs })
513            .field("destroys", &{ self.destroys })
514            .field("hash_grows", &{ self.hash_grows })
515            .field("res_failed", &{ self.res_failed })
516            .field("lookups", &{ self.lookups })
517            .field("hits", &{ self.hits })
518            .field("rcv_probes_mcast", &{ self.rcv_probes_mcast })
519            .field("rcv_probes_ucast", &{ self.rcv_probes_ucast })
520            .field("periodic_gc_runs", &{ self.periodic_gc_runs })
521            .field("forced_gc_runs", &{ self.forced_gc_runs })
522            .field("table_fulls", &{ self.table_fulls })
523            .finish()
524    }
525}
526#[derive(Clone)]
527pub enum NeighbourAttrs<'a> {
528    Unspec(&'a [u8]),
529    Dst(std::net::IpAddr),
530    Lladdr(&'a [u8]),
531    Cacheinfo(NdaCacheinfo),
532    Probes(u32),
533    Vlan(u16),
534    Port(u16),
535    Vni(u32),
536    Ifindex(u32),
537    Master(u32),
538    LinkNetnsid(i32),
539    SrcVni(u32),
540    Protocol(u8),
541    NhId(u32),
542    FdbExtAttrs(&'a [u8]),
543    #[doc = "Associated type: [`NtfExtFlags`] (enum)"]
544    FlagsExt(u32),
545    NdmStateMask(u16),
546    NdmFlagsMask(u8),
547}
548impl<'a> IterableNeighbourAttrs<'a> {
549    pub fn get_unspec(&self) -> Result<&'a [u8], ErrorContext> {
550        let mut iter = self.clone();
551        iter.pos = 0;
552        for attr in iter {
553            if let NeighbourAttrs::Unspec(val) = attr? {
554                return Ok(val);
555            }
556        }
557        Err(ErrorContext::new_missing(
558            "NeighbourAttrs",
559            "Unspec",
560            self.orig_loc,
561            self.buf.as_ptr() as usize,
562        ))
563    }
564    pub fn get_dst(&self) -> Result<std::net::IpAddr, ErrorContext> {
565        let mut iter = self.clone();
566        iter.pos = 0;
567        for attr in iter {
568            if let NeighbourAttrs::Dst(val) = attr? {
569                return Ok(val);
570            }
571        }
572        Err(ErrorContext::new_missing(
573            "NeighbourAttrs",
574            "Dst",
575            self.orig_loc,
576            self.buf.as_ptr() as usize,
577        ))
578    }
579    pub fn get_lladdr(&self) -> Result<&'a [u8], ErrorContext> {
580        let mut iter = self.clone();
581        iter.pos = 0;
582        for attr in iter {
583            if let NeighbourAttrs::Lladdr(val) = attr? {
584                return Ok(val);
585            }
586        }
587        Err(ErrorContext::new_missing(
588            "NeighbourAttrs",
589            "Lladdr",
590            self.orig_loc,
591            self.buf.as_ptr() as usize,
592        ))
593    }
594    pub fn get_cacheinfo(&self) -> Result<NdaCacheinfo, ErrorContext> {
595        let mut iter = self.clone();
596        iter.pos = 0;
597        for attr in iter {
598            if let NeighbourAttrs::Cacheinfo(val) = attr? {
599                return Ok(val);
600            }
601        }
602        Err(ErrorContext::new_missing(
603            "NeighbourAttrs",
604            "Cacheinfo",
605            self.orig_loc,
606            self.buf.as_ptr() as usize,
607        ))
608    }
609    pub fn get_probes(&self) -> Result<u32, ErrorContext> {
610        let mut iter = self.clone();
611        iter.pos = 0;
612        for attr in iter {
613            if let NeighbourAttrs::Probes(val) = attr? {
614                return Ok(val);
615            }
616        }
617        Err(ErrorContext::new_missing(
618            "NeighbourAttrs",
619            "Probes",
620            self.orig_loc,
621            self.buf.as_ptr() as usize,
622        ))
623    }
624    pub fn get_vlan(&self) -> Result<u16, ErrorContext> {
625        let mut iter = self.clone();
626        iter.pos = 0;
627        for attr in iter {
628            if let NeighbourAttrs::Vlan(val) = attr? {
629                return Ok(val);
630            }
631        }
632        Err(ErrorContext::new_missing(
633            "NeighbourAttrs",
634            "Vlan",
635            self.orig_loc,
636            self.buf.as_ptr() as usize,
637        ))
638    }
639    pub fn get_port(&self) -> Result<u16, ErrorContext> {
640        let mut iter = self.clone();
641        iter.pos = 0;
642        for attr in iter {
643            if let NeighbourAttrs::Port(val) = attr? {
644                return Ok(val);
645            }
646        }
647        Err(ErrorContext::new_missing(
648            "NeighbourAttrs",
649            "Port",
650            self.orig_loc,
651            self.buf.as_ptr() as usize,
652        ))
653    }
654    pub fn get_vni(&self) -> Result<u32, ErrorContext> {
655        let mut iter = self.clone();
656        iter.pos = 0;
657        for attr in iter {
658            if let NeighbourAttrs::Vni(val) = attr? {
659                return Ok(val);
660            }
661        }
662        Err(ErrorContext::new_missing(
663            "NeighbourAttrs",
664            "Vni",
665            self.orig_loc,
666            self.buf.as_ptr() as usize,
667        ))
668    }
669    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
670        let mut iter = self.clone();
671        iter.pos = 0;
672        for attr in iter {
673            if let NeighbourAttrs::Ifindex(val) = attr? {
674                return Ok(val);
675            }
676        }
677        Err(ErrorContext::new_missing(
678            "NeighbourAttrs",
679            "Ifindex",
680            self.orig_loc,
681            self.buf.as_ptr() as usize,
682        ))
683    }
684    pub fn get_master(&self) -> Result<u32, ErrorContext> {
685        let mut iter = self.clone();
686        iter.pos = 0;
687        for attr in iter {
688            if let NeighbourAttrs::Master(val) = attr? {
689                return Ok(val);
690            }
691        }
692        Err(ErrorContext::new_missing(
693            "NeighbourAttrs",
694            "Master",
695            self.orig_loc,
696            self.buf.as_ptr() as usize,
697        ))
698    }
699    pub fn get_link_netnsid(&self) -> Result<i32, ErrorContext> {
700        let mut iter = self.clone();
701        iter.pos = 0;
702        for attr in iter {
703            if let NeighbourAttrs::LinkNetnsid(val) = attr? {
704                return Ok(val);
705            }
706        }
707        Err(ErrorContext::new_missing(
708            "NeighbourAttrs",
709            "LinkNetnsid",
710            self.orig_loc,
711            self.buf.as_ptr() as usize,
712        ))
713    }
714    pub fn get_src_vni(&self) -> Result<u32, ErrorContext> {
715        let mut iter = self.clone();
716        iter.pos = 0;
717        for attr in iter {
718            if let NeighbourAttrs::SrcVni(val) = attr? {
719                return Ok(val);
720            }
721        }
722        Err(ErrorContext::new_missing(
723            "NeighbourAttrs",
724            "SrcVni",
725            self.orig_loc,
726            self.buf.as_ptr() as usize,
727        ))
728    }
729    pub fn get_protocol(&self) -> Result<u8, ErrorContext> {
730        let mut iter = self.clone();
731        iter.pos = 0;
732        for attr in iter {
733            if let NeighbourAttrs::Protocol(val) = attr? {
734                return Ok(val);
735            }
736        }
737        Err(ErrorContext::new_missing(
738            "NeighbourAttrs",
739            "Protocol",
740            self.orig_loc,
741            self.buf.as_ptr() as usize,
742        ))
743    }
744    pub fn get_nh_id(&self) -> Result<u32, ErrorContext> {
745        let mut iter = self.clone();
746        iter.pos = 0;
747        for attr in iter {
748            if let NeighbourAttrs::NhId(val) = attr? {
749                return Ok(val);
750            }
751        }
752        Err(ErrorContext::new_missing(
753            "NeighbourAttrs",
754            "NhId",
755            self.orig_loc,
756            self.buf.as_ptr() as usize,
757        ))
758    }
759    pub fn get_fdb_ext_attrs(&self) -> Result<&'a [u8], ErrorContext> {
760        let mut iter = self.clone();
761        iter.pos = 0;
762        for attr in iter {
763            if let NeighbourAttrs::FdbExtAttrs(val) = attr? {
764                return Ok(val);
765            }
766        }
767        Err(ErrorContext::new_missing(
768            "NeighbourAttrs",
769            "FdbExtAttrs",
770            self.orig_loc,
771            self.buf.as_ptr() as usize,
772        ))
773    }
774    #[doc = "Associated type: [`NtfExtFlags`] (enum)"]
775    pub fn get_flags_ext(&self) -> Result<u32, ErrorContext> {
776        let mut iter = self.clone();
777        iter.pos = 0;
778        for attr in iter {
779            if let NeighbourAttrs::FlagsExt(val) = attr? {
780                return Ok(val);
781            }
782        }
783        Err(ErrorContext::new_missing(
784            "NeighbourAttrs",
785            "FlagsExt",
786            self.orig_loc,
787            self.buf.as_ptr() as usize,
788        ))
789    }
790    pub fn get_ndm_state_mask(&self) -> Result<u16, ErrorContext> {
791        let mut iter = self.clone();
792        iter.pos = 0;
793        for attr in iter {
794            if let NeighbourAttrs::NdmStateMask(val) = attr? {
795                return Ok(val);
796            }
797        }
798        Err(ErrorContext::new_missing(
799            "NeighbourAttrs",
800            "NdmStateMask",
801            self.orig_loc,
802            self.buf.as_ptr() as usize,
803        ))
804    }
805    pub fn get_ndm_flags_mask(&self) -> Result<u8, ErrorContext> {
806        let mut iter = self.clone();
807        iter.pos = 0;
808        for attr in iter {
809            if let NeighbourAttrs::NdmFlagsMask(val) = attr? {
810                return Ok(val);
811            }
812        }
813        Err(ErrorContext::new_missing(
814            "NeighbourAttrs",
815            "NdmFlagsMask",
816            self.orig_loc,
817            self.buf.as_ptr() as usize,
818        ))
819    }
820}
821impl NeighbourAttrs<'_> {
822    pub fn new<'a>(buf: &'a [u8]) -> IterableNeighbourAttrs<'a> {
823        IterableNeighbourAttrs::with_loc(buf, buf.as_ptr() as usize)
824    }
825    fn attr_from_type(r#type: u16) -> Option<&'static str> {
826        let res = match r#type {
827            0u16 => "Unspec",
828            1u16 => "Dst",
829            2u16 => "Lladdr",
830            3u16 => "Cacheinfo",
831            4u16 => "Probes",
832            5u16 => "Vlan",
833            6u16 => "Port",
834            7u16 => "Vni",
835            8u16 => "Ifindex",
836            9u16 => "Master",
837            10u16 => "LinkNetnsid",
838            11u16 => "SrcVni",
839            12u16 => "Protocol",
840            13u16 => "NhId",
841            14u16 => "FdbExtAttrs",
842            15u16 => "FlagsExt",
843            16u16 => "NdmStateMask",
844            17u16 => "NdmFlagsMask",
845            _ => return None,
846        };
847        Some(res)
848    }
849}
850#[derive(Clone, Copy, Default)]
851pub struct IterableNeighbourAttrs<'a> {
852    buf: &'a [u8],
853    pos: usize,
854    orig_loc: usize,
855}
856impl<'a> IterableNeighbourAttrs<'a> {
857    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
858        Self {
859            buf,
860            pos: 0,
861            orig_loc,
862        }
863    }
864    pub fn get_buf(&self) -> &'a [u8] {
865        self.buf
866    }
867}
868impl<'a> Iterator for IterableNeighbourAttrs<'a> {
869    type Item = Result<NeighbourAttrs<'a>, ErrorContext>;
870    fn next(&mut self) -> Option<Self::Item> {
871        let pos = self.pos;
872        let mut r#type;
873        loop {
874            r#type = None;
875            if self.buf.len() == self.pos {
876                return None;
877            }
878            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
879                break;
880            };
881            r#type = Some(header.r#type);
882            let res = match header.r#type {
883                0u16 => NeighbourAttrs::Unspec({
884                    let res = Some(next);
885                    let Some(val) = res else { break };
886                    val
887                }),
888                1u16 => NeighbourAttrs::Dst({
889                    let res = parse_ip(next);
890                    let Some(val) = res else { break };
891                    val
892                }),
893                2u16 => NeighbourAttrs::Lladdr({
894                    let res = Some(next);
895                    let Some(val) = res else { break };
896                    val
897                }),
898                3u16 => NeighbourAttrs::Cacheinfo({
899                    let res = Some(NdaCacheinfo::new_from_zeroed(next));
900                    let Some(val) = res else { break };
901                    val
902                }),
903                4u16 => NeighbourAttrs::Probes({
904                    let res = parse_u32(next);
905                    let Some(val) = res else { break };
906                    val
907                }),
908                5u16 => NeighbourAttrs::Vlan({
909                    let res = parse_u16(next);
910                    let Some(val) = res else { break };
911                    val
912                }),
913                6u16 => NeighbourAttrs::Port({
914                    let res = parse_u16(next);
915                    let Some(val) = res else { break };
916                    val
917                }),
918                7u16 => NeighbourAttrs::Vni({
919                    let res = parse_u32(next);
920                    let Some(val) = res else { break };
921                    val
922                }),
923                8u16 => NeighbourAttrs::Ifindex({
924                    let res = parse_u32(next);
925                    let Some(val) = res else { break };
926                    val
927                }),
928                9u16 => NeighbourAttrs::Master({
929                    let res = parse_u32(next);
930                    let Some(val) = res else { break };
931                    val
932                }),
933                10u16 => NeighbourAttrs::LinkNetnsid({
934                    let res = parse_i32(next);
935                    let Some(val) = res else { break };
936                    val
937                }),
938                11u16 => NeighbourAttrs::SrcVni({
939                    let res = parse_u32(next);
940                    let Some(val) = res else { break };
941                    val
942                }),
943                12u16 => NeighbourAttrs::Protocol({
944                    let res = parse_u8(next);
945                    let Some(val) = res else { break };
946                    val
947                }),
948                13u16 => NeighbourAttrs::NhId({
949                    let res = parse_u32(next);
950                    let Some(val) = res else { break };
951                    val
952                }),
953                14u16 => NeighbourAttrs::FdbExtAttrs({
954                    let res = Some(next);
955                    let Some(val) = res else { break };
956                    val
957                }),
958                15u16 => NeighbourAttrs::FlagsExt({
959                    let res = parse_u32(next);
960                    let Some(val) = res else { break };
961                    val
962                }),
963                16u16 => NeighbourAttrs::NdmStateMask({
964                    let res = parse_u16(next);
965                    let Some(val) = res else { break };
966                    val
967                }),
968                17u16 => NeighbourAttrs::NdmFlagsMask({
969                    let res = parse_u8(next);
970                    let Some(val) = res else { break };
971                    val
972                }),
973                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
974                n => continue,
975            };
976            return Some(Ok(res));
977        }
978        Some(Err(ErrorContext::new(
979            "NeighbourAttrs",
980            r#type.and_then(|t| NeighbourAttrs::attr_from_type(t)),
981            self.orig_loc,
982            self.buf.as_ptr().wrapping_add(pos) as usize,
983        )))
984    }
985}
986impl<'a> std::fmt::Debug for IterableNeighbourAttrs<'_> {
987    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
988        let mut fmt = f.debug_struct("NeighbourAttrs");
989        for attr in self.clone() {
990            let attr = match attr {
991                Ok(a) => a,
992                Err(err) => {
993                    fmt.finish()?;
994                    f.write_str("Err(")?;
995                    err.fmt(f)?;
996                    return f.write_str(")");
997                }
998            };
999            match attr {
1000                NeighbourAttrs::Unspec(val) => fmt.field("Unspec", &val),
1001                NeighbourAttrs::Dst(val) => fmt.field("Dst", &val),
1002                NeighbourAttrs::Lladdr(val) => fmt.field("Lladdr", &FormatMac(val)),
1003                NeighbourAttrs::Cacheinfo(val) => fmt.field("Cacheinfo", &val),
1004                NeighbourAttrs::Probes(val) => fmt.field("Probes", &val),
1005                NeighbourAttrs::Vlan(val) => fmt.field("Vlan", &val),
1006                NeighbourAttrs::Port(val) => fmt.field("Port", &val),
1007                NeighbourAttrs::Vni(val) => fmt.field("Vni", &val),
1008                NeighbourAttrs::Ifindex(val) => fmt.field("Ifindex", &val),
1009                NeighbourAttrs::Master(val) => fmt.field("Master", &val),
1010                NeighbourAttrs::LinkNetnsid(val) => fmt.field("LinkNetnsid", &val),
1011                NeighbourAttrs::SrcVni(val) => fmt.field("SrcVni", &val),
1012                NeighbourAttrs::Protocol(val) => fmt.field("Protocol", &val),
1013                NeighbourAttrs::NhId(val) => fmt.field("NhId", &val),
1014                NeighbourAttrs::FdbExtAttrs(val) => fmt.field("FdbExtAttrs", &val),
1015                NeighbourAttrs::FlagsExt(val) => fmt.field(
1016                    "FlagsExt",
1017                    &FormatFlags(val.into(), NtfExtFlags::from_value),
1018                ),
1019                NeighbourAttrs::NdmStateMask(val) => fmt.field("NdmStateMask", &val),
1020                NeighbourAttrs::NdmFlagsMask(val) => fmt.field("NdmFlagsMask", &val),
1021            };
1022        }
1023        fmt.finish()
1024    }
1025}
1026impl IterableNeighbourAttrs<'_> {
1027    pub fn lookup_attr(
1028        &self,
1029        offset: usize,
1030        missing_type: Option<u16>,
1031    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1032        let mut stack = Vec::new();
1033        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1034        if missing_type.is_some() && cur == offset {
1035            stack.push(("NeighbourAttrs", offset));
1036            return (
1037                stack,
1038                missing_type.and_then(|t| NeighbourAttrs::attr_from_type(t)),
1039            );
1040        }
1041        if cur > offset || cur + self.buf.len() < offset {
1042            return (stack, None);
1043        }
1044        let mut attrs = self.clone();
1045        let mut last_off = cur + attrs.pos;
1046        while let Some(attr) = attrs.next() {
1047            let Ok(attr) = attr else { break };
1048            match attr {
1049                NeighbourAttrs::Unspec(val) => {
1050                    if last_off == offset {
1051                        stack.push(("Unspec", last_off));
1052                        break;
1053                    }
1054                }
1055                NeighbourAttrs::Dst(val) => {
1056                    if last_off == offset {
1057                        stack.push(("Dst", last_off));
1058                        break;
1059                    }
1060                }
1061                NeighbourAttrs::Lladdr(val) => {
1062                    if last_off == offset {
1063                        stack.push(("Lladdr", last_off));
1064                        break;
1065                    }
1066                }
1067                NeighbourAttrs::Cacheinfo(val) => {
1068                    if last_off == offset {
1069                        stack.push(("Cacheinfo", last_off));
1070                        break;
1071                    }
1072                }
1073                NeighbourAttrs::Probes(val) => {
1074                    if last_off == offset {
1075                        stack.push(("Probes", last_off));
1076                        break;
1077                    }
1078                }
1079                NeighbourAttrs::Vlan(val) => {
1080                    if last_off == offset {
1081                        stack.push(("Vlan", last_off));
1082                        break;
1083                    }
1084                }
1085                NeighbourAttrs::Port(val) => {
1086                    if last_off == offset {
1087                        stack.push(("Port", last_off));
1088                        break;
1089                    }
1090                }
1091                NeighbourAttrs::Vni(val) => {
1092                    if last_off == offset {
1093                        stack.push(("Vni", last_off));
1094                        break;
1095                    }
1096                }
1097                NeighbourAttrs::Ifindex(val) => {
1098                    if last_off == offset {
1099                        stack.push(("Ifindex", last_off));
1100                        break;
1101                    }
1102                }
1103                NeighbourAttrs::Master(val) => {
1104                    if last_off == offset {
1105                        stack.push(("Master", last_off));
1106                        break;
1107                    }
1108                }
1109                NeighbourAttrs::LinkNetnsid(val) => {
1110                    if last_off == offset {
1111                        stack.push(("LinkNetnsid", last_off));
1112                        break;
1113                    }
1114                }
1115                NeighbourAttrs::SrcVni(val) => {
1116                    if last_off == offset {
1117                        stack.push(("SrcVni", last_off));
1118                        break;
1119                    }
1120                }
1121                NeighbourAttrs::Protocol(val) => {
1122                    if last_off == offset {
1123                        stack.push(("Protocol", last_off));
1124                        break;
1125                    }
1126                }
1127                NeighbourAttrs::NhId(val) => {
1128                    if last_off == offset {
1129                        stack.push(("NhId", last_off));
1130                        break;
1131                    }
1132                }
1133                NeighbourAttrs::FdbExtAttrs(val) => {
1134                    if last_off == offset {
1135                        stack.push(("FdbExtAttrs", last_off));
1136                        break;
1137                    }
1138                }
1139                NeighbourAttrs::FlagsExt(val) => {
1140                    if last_off == offset {
1141                        stack.push(("FlagsExt", last_off));
1142                        break;
1143                    }
1144                }
1145                NeighbourAttrs::NdmStateMask(val) => {
1146                    if last_off == offset {
1147                        stack.push(("NdmStateMask", last_off));
1148                        break;
1149                    }
1150                }
1151                NeighbourAttrs::NdmFlagsMask(val) => {
1152                    if last_off == offset {
1153                        stack.push(("NdmFlagsMask", last_off));
1154                        break;
1155                    }
1156                }
1157                _ => {}
1158            };
1159            last_off = cur + attrs.pos;
1160        }
1161        if !stack.is_empty() {
1162            stack.push(("NeighbourAttrs", cur));
1163        }
1164        (stack, None)
1165    }
1166}
1167#[derive(Clone)]
1168pub enum NdtAttrs<'a> {
1169    Name(&'a CStr),
1170    Thresh1(u32),
1171    Thresh2(u32),
1172    Thresh3(u32),
1173    Config(NdtConfig),
1174    Parms(IterableNdtpaAttrs<'a>),
1175    Stats(NdtStats),
1176    GcInterval(u64),
1177    Pad(&'a [u8]),
1178}
1179impl<'a> IterableNdtAttrs<'a> {
1180    pub fn get_name(&self) -> Result<&'a CStr, ErrorContext> {
1181        let mut iter = self.clone();
1182        iter.pos = 0;
1183        for attr in iter {
1184            if let NdtAttrs::Name(val) = attr? {
1185                return Ok(val);
1186            }
1187        }
1188        Err(ErrorContext::new_missing(
1189            "NdtAttrs",
1190            "Name",
1191            self.orig_loc,
1192            self.buf.as_ptr() as usize,
1193        ))
1194    }
1195    pub fn get_thresh1(&self) -> Result<u32, ErrorContext> {
1196        let mut iter = self.clone();
1197        iter.pos = 0;
1198        for attr in iter {
1199            if let NdtAttrs::Thresh1(val) = attr? {
1200                return Ok(val);
1201            }
1202        }
1203        Err(ErrorContext::new_missing(
1204            "NdtAttrs",
1205            "Thresh1",
1206            self.orig_loc,
1207            self.buf.as_ptr() as usize,
1208        ))
1209    }
1210    pub fn get_thresh2(&self) -> Result<u32, ErrorContext> {
1211        let mut iter = self.clone();
1212        iter.pos = 0;
1213        for attr in iter {
1214            if let NdtAttrs::Thresh2(val) = attr? {
1215                return Ok(val);
1216            }
1217        }
1218        Err(ErrorContext::new_missing(
1219            "NdtAttrs",
1220            "Thresh2",
1221            self.orig_loc,
1222            self.buf.as_ptr() as usize,
1223        ))
1224    }
1225    pub fn get_thresh3(&self) -> Result<u32, ErrorContext> {
1226        let mut iter = self.clone();
1227        iter.pos = 0;
1228        for attr in iter {
1229            if let NdtAttrs::Thresh3(val) = attr? {
1230                return Ok(val);
1231            }
1232        }
1233        Err(ErrorContext::new_missing(
1234            "NdtAttrs",
1235            "Thresh3",
1236            self.orig_loc,
1237            self.buf.as_ptr() as usize,
1238        ))
1239    }
1240    pub fn get_config(&self) -> Result<NdtConfig, ErrorContext> {
1241        let mut iter = self.clone();
1242        iter.pos = 0;
1243        for attr in iter {
1244            if let NdtAttrs::Config(val) = attr? {
1245                return Ok(val);
1246            }
1247        }
1248        Err(ErrorContext::new_missing(
1249            "NdtAttrs",
1250            "Config",
1251            self.orig_loc,
1252            self.buf.as_ptr() as usize,
1253        ))
1254    }
1255    pub fn get_parms(&self) -> Result<IterableNdtpaAttrs<'a>, ErrorContext> {
1256        let mut iter = self.clone();
1257        iter.pos = 0;
1258        for attr in iter {
1259            if let NdtAttrs::Parms(val) = attr? {
1260                return Ok(val);
1261            }
1262        }
1263        Err(ErrorContext::new_missing(
1264            "NdtAttrs",
1265            "Parms",
1266            self.orig_loc,
1267            self.buf.as_ptr() as usize,
1268        ))
1269    }
1270    pub fn get_stats(&self) -> Result<NdtStats, ErrorContext> {
1271        let mut iter = self.clone();
1272        iter.pos = 0;
1273        for attr in iter {
1274            if let NdtAttrs::Stats(val) = attr? {
1275                return Ok(val);
1276            }
1277        }
1278        Err(ErrorContext::new_missing(
1279            "NdtAttrs",
1280            "Stats",
1281            self.orig_loc,
1282            self.buf.as_ptr() as usize,
1283        ))
1284    }
1285    pub fn get_gc_interval(&self) -> Result<u64, ErrorContext> {
1286        let mut iter = self.clone();
1287        iter.pos = 0;
1288        for attr in iter {
1289            if let NdtAttrs::GcInterval(val) = attr? {
1290                return Ok(val);
1291            }
1292        }
1293        Err(ErrorContext::new_missing(
1294            "NdtAttrs",
1295            "GcInterval",
1296            self.orig_loc,
1297            self.buf.as_ptr() as usize,
1298        ))
1299    }
1300    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
1301        let mut iter = self.clone();
1302        iter.pos = 0;
1303        for attr in iter {
1304            if let NdtAttrs::Pad(val) = attr? {
1305                return Ok(val);
1306            }
1307        }
1308        Err(ErrorContext::new_missing(
1309            "NdtAttrs",
1310            "Pad",
1311            self.orig_loc,
1312            self.buf.as_ptr() as usize,
1313        ))
1314    }
1315}
1316impl NdtAttrs<'_> {
1317    pub fn new<'a>(buf: &'a [u8]) -> IterableNdtAttrs<'a> {
1318        IterableNdtAttrs::with_loc(buf, buf.as_ptr() as usize)
1319    }
1320    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1321        let res = match r#type {
1322            1u16 => "Name",
1323            2u16 => "Thresh1",
1324            3u16 => "Thresh2",
1325            4u16 => "Thresh3",
1326            5u16 => "Config",
1327            6u16 => "Parms",
1328            7u16 => "Stats",
1329            8u16 => "GcInterval",
1330            9u16 => "Pad",
1331            _ => return None,
1332        };
1333        Some(res)
1334    }
1335}
1336#[derive(Clone, Copy, Default)]
1337pub struct IterableNdtAttrs<'a> {
1338    buf: &'a [u8],
1339    pos: usize,
1340    orig_loc: usize,
1341}
1342impl<'a> IterableNdtAttrs<'a> {
1343    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1344        Self {
1345            buf,
1346            pos: 0,
1347            orig_loc,
1348        }
1349    }
1350    pub fn get_buf(&self) -> &'a [u8] {
1351        self.buf
1352    }
1353}
1354impl<'a> Iterator for IterableNdtAttrs<'a> {
1355    type Item = Result<NdtAttrs<'a>, ErrorContext>;
1356    fn next(&mut self) -> Option<Self::Item> {
1357        let pos = self.pos;
1358        let mut r#type;
1359        loop {
1360            r#type = None;
1361            if self.buf.len() == self.pos {
1362                return None;
1363            }
1364            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1365                break;
1366            };
1367            r#type = Some(header.r#type);
1368            let res = match header.r#type {
1369                1u16 => NdtAttrs::Name({
1370                    let res = CStr::from_bytes_with_nul(next).ok();
1371                    let Some(val) = res else { break };
1372                    val
1373                }),
1374                2u16 => NdtAttrs::Thresh1({
1375                    let res = parse_u32(next);
1376                    let Some(val) = res else { break };
1377                    val
1378                }),
1379                3u16 => NdtAttrs::Thresh2({
1380                    let res = parse_u32(next);
1381                    let Some(val) = res else { break };
1382                    val
1383                }),
1384                4u16 => NdtAttrs::Thresh3({
1385                    let res = parse_u32(next);
1386                    let Some(val) = res else { break };
1387                    val
1388                }),
1389                5u16 => NdtAttrs::Config({
1390                    let res = Some(NdtConfig::new_from_zeroed(next));
1391                    let Some(val) = res else { break };
1392                    val
1393                }),
1394                6u16 => NdtAttrs::Parms({
1395                    let res = Some(IterableNdtpaAttrs::with_loc(next, self.orig_loc));
1396                    let Some(val) = res else { break };
1397                    val
1398                }),
1399                7u16 => NdtAttrs::Stats({
1400                    let res = Some(NdtStats::new_from_zeroed(next));
1401                    let Some(val) = res else { break };
1402                    val
1403                }),
1404                8u16 => NdtAttrs::GcInterval({
1405                    let res = parse_u64(next);
1406                    let Some(val) = res else { break };
1407                    val
1408                }),
1409                9u16 => NdtAttrs::Pad({
1410                    let res = Some(next);
1411                    let Some(val) = res else { break };
1412                    val
1413                }),
1414                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1415                n => continue,
1416            };
1417            return Some(Ok(res));
1418        }
1419        Some(Err(ErrorContext::new(
1420            "NdtAttrs",
1421            r#type.and_then(|t| NdtAttrs::attr_from_type(t)),
1422            self.orig_loc,
1423            self.buf.as_ptr().wrapping_add(pos) as usize,
1424        )))
1425    }
1426}
1427impl<'a> std::fmt::Debug for IterableNdtAttrs<'_> {
1428    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1429        let mut fmt = f.debug_struct("NdtAttrs");
1430        for attr in self.clone() {
1431            let attr = match attr {
1432                Ok(a) => a,
1433                Err(err) => {
1434                    fmt.finish()?;
1435                    f.write_str("Err(")?;
1436                    err.fmt(f)?;
1437                    return f.write_str(")");
1438                }
1439            };
1440            match attr {
1441                NdtAttrs::Name(val) => fmt.field("Name", &val),
1442                NdtAttrs::Thresh1(val) => fmt.field("Thresh1", &val),
1443                NdtAttrs::Thresh2(val) => fmt.field("Thresh2", &val),
1444                NdtAttrs::Thresh3(val) => fmt.field("Thresh3", &val),
1445                NdtAttrs::Config(val) => fmt.field("Config", &val),
1446                NdtAttrs::Parms(val) => fmt.field("Parms", &val),
1447                NdtAttrs::Stats(val) => fmt.field("Stats", &val),
1448                NdtAttrs::GcInterval(val) => fmt.field("GcInterval", &val),
1449                NdtAttrs::Pad(val) => fmt.field("Pad", &val),
1450            };
1451        }
1452        fmt.finish()
1453    }
1454}
1455impl IterableNdtAttrs<'_> {
1456    pub fn lookup_attr(
1457        &self,
1458        offset: usize,
1459        missing_type: Option<u16>,
1460    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1461        let mut stack = Vec::new();
1462        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1463        if missing_type.is_some() && cur == offset {
1464            stack.push(("NdtAttrs", offset));
1465            return (
1466                stack,
1467                missing_type.and_then(|t| NdtAttrs::attr_from_type(t)),
1468            );
1469        }
1470        if cur > offset || cur + self.buf.len() < offset {
1471            return (stack, None);
1472        }
1473        let mut attrs = self.clone();
1474        let mut last_off = cur + attrs.pos;
1475        let mut missing = None;
1476        while let Some(attr) = attrs.next() {
1477            let Ok(attr) = attr else { break };
1478            match attr {
1479                NdtAttrs::Name(val) => {
1480                    if last_off == offset {
1481                        stack.push(("Name", last_off));
1482                        break;
1483                    }
1484                }
1485                NdtAttrs::Thresh1(val) => {
1486                    if last_off == offset {
1487                        stack.push(("Thresh1", last_off));
1488                        break;
1489                    }
1490                }
1491                NdtAttrs::Thresh2(val) => {
1492                    if last_off == offset {
1493                        stack.push(("Thresh2", last_off));
1494                        break;
1495                    }
1496                }
1497                NdtAttrs::Thresh3(val) => {
1498                    if last_off == offset {
1499                        stack.push(("Thresh3", last_off));
1500                        break;
1501                    }
1502                }
1503                NdtAttrs::Config(val) => {
1504                    if last_off == offset {
1505                        stack.push(("Config", last_off));
1506                        break;
1507                    }
1508                }
1509                NdtAttrs::Parms(val) => {
1510                    (stack, missing) = val.lookup_attr(offset, missing_type);
1511                    if !stack.is_empty() {
1512                        break;
1513                    }
1514                }
1515                NdtAttrs::Stats(val) => {
1516                    if last_off == offset {
1517                        stack.push(("Stats", last_off));
1518                        break;
1519                    }
1520                }
1521                NdtAttrs::GcInterval(val) => {
1522                    if last_off == offset {
1523                        stack.push(("GcInterval", last_off));
1524                        break;
1525                    }
1526                }
1527                NdtAttrs::Pad(val) => {
1528                    if last_off == offset {
1529                        stack.push(("Pad", last_off));
1530                        break;
1531                    }
1532                }
1533                _ => {}
1534            };
1535            last_off = cur + attrs.pos;
1536        }
1537        if !stack.is_empty() {
1538            stack.push(("NdtAttrs", cur));
1539        }
1540        (stack, missing)
1541    }
1542}
1543#[derive(Clone)]
1544pub enum NdtpaAttrs<'a> {
1545    Ifindex(u32),
1546    Refcnt(u32),
1547    ReachableTime(u64),
1548    BaseReachableTime(u64),
1549    RetransTime(u64),
1550    GcStaletime(u64),
1551    DelayProbeTime(u64),
1552    QueueLen(u32),
1553    AppProbes(u32),
1554    UcastProbes(u32),
1555    McastProbes(u32),
1556    AnycastDelay(u64),
1557    ProxyDelay(u64),
1558    ProxyQlen(u32),
1559    Locktime(u64),
1560    QueueLenbytes(u32),
1561    McastReprobes(u32),
1562    Pad(&'a [u8]),
1563    IntervalProbeTimeMs(u64),
1564}
1565impl<'a> IterableNdtpaAttrs<'a> {
1566    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
1567        let mut iter = self.clone();
1568        iter.pos = 0;
1569        for attr in iter {
1570            if let NdtpaAttrs::Ifindex(val) = attr? {
1571                return Ok(val);
1572            }
1573        }
1574        Err(ErrorContext::new_missing(
1575            "NdtpaAttrs",
1576            "Ifindex",
1577            self.orig_loc,
1578            self.buf.as_ptr() as usize,
1579        ))
1580    }
1581    pub fn get_refcnt(&self) -> Result<u32, ErrorContext> {
1582        let mut iter = self.clone();
1583        iter.pos = 0;
1584        for attr in iter {
1585            if let NdtpaAttrs::Refcnt(val) = attr? {
1586                return Ok(val);
1587            }
1588        }
1589        Err(ErrorContext::new_missing(
1590            "NdtpaAttrs",
1591            "Refcnt",
1592            self.orig_loc,
1593            self.buf.as_ptr() as usize,
1594        ))
1595    }
1596    pub fn get_reachable_time(&self) -> Result<u64, ErrorContext> {
1597        let mut iter = self.clone();
1598        iter.pos = 0;
1599        for attr in iter {
1600            if let NdtpaAttrs::ReachableTime(val) = attr? {
1601                return Ok(val);
1602            }
1603        }
1604        Err(ErrorContext::new_missing(
1605            "NdtpaAttrs",
1606            "ReachableTime",
1607            self.orig_loc,
1608            self.buf.as_ptr() as usize,
1609        ))
1610    }
1611    pub fn get_base_reachable_time(&self) -> Result<u64, ErrorContext> {
1612        let mut iter = self.clone();
1613        iter.pos = 0;
1614        for attr in iter {
1615            if let NdtpaAttrs::BaseReachableTime(val) = attr? {
1616                return Ok(val);
1617            }
1618        }
1619        Err(ErrorContext::new_missing(
1620            "NdtpaAttrs",
1621            "BaseReachableTime",
1622            self.orig_loc,
1623            self.buf.as_ptr() as usize,
1624        ))
1625    }
1626    pub fn get_retrans_time(&self) -> Result<u64, ErrorContext> {
1627        let mut iter = self.clone();
1628        iter.pos = 0;
1629        for attr in iter {
1630            if let NdtpaAttrs::RetransTime(val) = attr? {
1631                return Ok(val);
1632            }
1633        }
1634        Err(ErrorContext::new_missing(
1635            "NdtpaAttrs",
1636            "RetransTime",
1637            self.orig_loc,
1638            self.buf.as_ptr() as usize,
1639        ))
1640    }
1641    pub fn get_gc_staletime(&self) -> Result<u64, ErrorContext> {
1642        let mut iter = self.clone();
1643        iter.pos = 0;
1644        for attr in iter {
1645            if let NdtpaAttrs::GcStaletime(val) = attr? {
1646                return Ok(val);
1647            }
1648        }
1649        Err(ErrorContext::new_missing(
1650            "NdtpaAttrs",
1651            "GcStaletime",
1652            self.orig_loc,
1653            self.buf.as_ptr() as usize,
1654        ))
1655    }
1656    pub fn get_delay_probe_time(&self) -> Result<u64, ErrorContext> {
1657        let mut iter = self.clone();
1658        iter.pos = 0;
1659        for attr in iter {
1660            if let NdtpaAttrs::DelayProbeTime(val) = attr? {
1661                return Ok(val);
1662            }
1663        }
1664        Err(ErrorContext::new_missing(
1665            "NdtpaAttrs",
1666            "DelayProbeTime",
1667            self.orig_loc,
1668            self.buf.as_ptr() as usize,
1669        ))
1670    }
1671    pub fn get_queue_len(&self) -> Result<u32, ErrorContext> {
1672        let mut iter = self.clone();
1673        iter.pos = 0;
1674        for attr in iter {
1675            if let NdtpaAttrs::QueueLen(val) = attr? {
1676                return Ok(val);
1677            }
1678        }
1679        Err(ErrorContext::new_missing(
1680            "NdtpaAttrs",
1681            "QueueLen",
1682            self.orig_loc,
1683            self.buf.as_ptr() as usize,
1684        ))
1685    }
1686    pub fn get_app_probes(&self) -> Result<u32, ErrorContext> {
1687        let mut iter = self.clone();
1688        iter.pos = 0;
1689        for attr in iter {
1690            if let NdtpaAttrs::AppProbes(val) = attr? {
1691                return Ok(val);
1692            }
1693        }
1694        Err(ErrorContext::new_missing(
1695            "NdtpaAttrs",
1696            "AppProbes",
1697            self.orig_loc,
1698            self.buf.as_ptr() as usize,
1699        ))
1700    }
1701    pub fn get_ucast_probes(&self) -> Result<u32, ErrorContext> {
1702        let mut iter = self.clone();
1703        iter.pos = 0;
1704        for attr in iter {
1705            if let NdtpaAttrs::UcastProbes(val) = attr? {
1706                return Ok(val);
1707            }
1708        }
1709        Err(ErrorContext::new_missing(
1710            "NdtpaAttrs",
1711            "UcastProbes",
1712            self.orig_loc,
1713            self.buf.as_ptr() as usize,
1714        ))
1715    }
1716    pub fn get_mcast_probes(&self) -> Result<u32, ErrorContext> {
1717        let mut iter = self.clone();
1718        iter.pos = 0;
1719        for attr in iter {
1720            if let NdtpaAttrs::McastProbes(val) = attr? {
1721                return Ok(val);
1722            }
1723        }
1724        Err(ErrorContext::new_missing(
1725            "NdtpaAttrs",
1726            "McastProbes",
1727            self.orig_loc,
1728            self.buf.as_ptr() as usize,
1729        ))
1730    }
1731    pub fn get_anycast_delay(&self) -> Result<u64, ErrorContext> {
1732        let mut iter = self.clone();
1733        iter.pos = 0;
1734        for attr in iter {
1735            if let NdtpaAttrs::AnycastDelay(val) = attr? {
1736                return Ok(val);
1737            }
1738        }
1739        Err(ErrorContext::new_missing(
1740            "NdtpaAttrs",
1741            "AnycastDelay",
1742            self.orig_loc,
1743            self.buf.as_ptr() as usize,
1744        ))
1745    }
1746    pub fn get_proxy_delay(&self) -> Result<u64, ErrorContext> {
1747        let mut iter = self.clone();
1748        iter.pos = 0;
1749        for attr in iter {
1750            if let NdtpaAttrs::ProxyDelay(val) = attr? {
1751                return Ok(val);
1752            }
1753        }
1754        Err(ErrorContext::new_missing(
1755            "NdtpaAttrs",
1756            "ProxyDelay",
1757            self.orig_loc,
1758            self.buf.as_ptr() as usize,
1759        ))
1760    }
1761    pub fn get_proxy_qlen(&self) -> Result<u32, ErrorContext> {
1762        let mut iter = self.clone();
1763        iter.pos = 0;
1764        for attr in iter {
1765            if let NdtpaAttrs::ProxyQlen(val) = attr? {
1766                return Ok(val);
1767            }
1768        }
1769        Err(ErrorContext::new_missing(
1770            "NdtpaAttrs",
1771            "ProxyQlen",
1772            self.orig_loc,
1773            self.buf.as_ptr() as usize,
1774        ))
1775    }
1776    pub fn get_locktime(&self) -> Result<u64, ErrorContext> {
1777        let mut iter = self.clone();
1778        iter.pos = 0;
1779        for attr in iter {
1780            if let NdtpaAttrs::Locktime(val) = attr? {
1781                return Ok(val);
1782            }
1783        }
1784        Err(ErrorContext::new_missing(
1785            "NdtpaAttrs",
1786            "Locktime",
1787            self.orig_loc,
1788            self.buf.as_ptr() as usize,
1789        ))
1790    }
1791    pub fn get_queue_lenbytes(&self) -> Result<u32, ErrorContext> {
1792        let mut iter = self.clone();
1793        iter.pos = 0;
1794        for attr in iter {
1795            if let NdtpaAttrs::QueueLenbytes(val) = attr? {
1796                return Ok(val);
1797            }
1798        }
1799        Err(ErrorContext::new_missing(
1800            "NdtpaAttrs",
1801            "QueueLenbytes",
1802            self.orig_loc,
1803            self.buf.as_ptr() as usize,
1804        ))
1805    }
1806    pub fn get_mcast_reprobes(&self) -> Result<u32, ErrorContext> {
1807        let mut iter = self.clone();
1808        iter.pos = 0;
1809        for attr in iter {
1810            if let NdtpaAttrs::McastReprobes(val) = attr? {
1811                return Ok(val);
1812            }
1813        }
1814        Err(ErrorContext::new_missing(
1815            "NdtpaAttrs",
1816            "McastReprobes",
1817            self.orig_loc,
1818            self.buf.as_ptr() as usize,
1819        ))
1820    }
1821    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
1822        let mut iter = self.clone();
1823        iter.pos = 0;
1824        for attr in iter {
1825            if let NdtpaAttrs::Pad(val) = attr? {
1826                return Ok(val);
1827            }
1828        }
1829        Err(ErrorContext::new_missing(
1830            "NdtpaAttrs",
1831            "Pad",
1832            self.orig_loc,
1833            self.buf.as_ptr() as usize,
1834        ))
1835    }
1836    pub fn get_interval_probe_time_ms(&self) -> Result<u64, ErrorContext> {
1837        let mut iter = self.clone();
1838        iter.pos = 0;
1839        for attr in iter {
1840            if let NdtpaAttrs::IntervalProbeTimeMs(val) = attr? {
1841                return Ok(val);
1842            }
1843        }
1844        Err(ErrorContext::new_missing(
1845            "NdtpaAttrs",
1846            "IntervalProbeTimeMs",
1847            self.orig_loc,
1848            self.buf.as_ptr() as usize,
1849        ))
1850    }
1851}
1852impl NdtpaAttrs<'_> {
1853    pub fn new<'a>(buf: &'a [u8]) -> IterableNdtpaAttrs<'a> {
1854        IterableNdtpaAttrs::with_loc(buf, buf.as_ptr() as usize)
1855    }
1856    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1857        let res = match r#type {
1858            1u16 => "Ifindex",
1859            2u16 => "Refcnt",
1860            3u16 => "ReachableTime",
1861            4u16 => "BaseReachableTime",
1862            5u16 => "RetransTime",
1863            6u16 => "GcStaletime",
1864            7u16 => "DelayProbeTime",
1865            8u16 => "QueueLen",
1866            9u16 => "AppProbes",
1867            10u16 => "UcastProbes",
1868            11u16 => "McastProbes",
1869            12u16 => "AnycastDelay",
1870            13u16 => "ProxyDelay",
1871            14u16 => "ProxyQlen",
1872            15u16 => "Locktime",
1873            16u16 => "QueueLenbytes",
1874            17u16 => "McastReprobes",
1875            18u16 => "Pad",
1876            19u16 => "IntervalProbeTimeMs",
1877            _ => return None,
1878        };
1879        Some(res)
1880    }
1881}
1882#[derive(Clone, Copy, Default)]
1883pub struct IterableNdtpaAttrs<'a> {
1884    buf: &'a [u8],
1885    pos: usize,
1886    orig_loc: usize,
1887}
1888impl<'a> IterableNdtpaAttrs<'a> {
1889    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1890        Self {
1891            buf,
1892            pos: 0,
1893            orig_loc,
1894        }
1895    }
1896    pub fn get_buf(&self) -> &'a [u8] {
1897        self.buf
1898    }
1899}
1900impl<'a> Iterator for IterableNdtpaAttrs<'a> {
1901    type Item = Result<NdtpaAttrs<'a>, ErrorContext>;
1902    fn next(&mut self) -> Option<Self::Item> {
1903        let pos = self.pos;
1904        let mut r#type;
1905        loop {
1906            r#type = None;
1907            if self.buf.len() == self.pos {
1908                return None;
1909            }
1910            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1911                break;
1912            };
1913            r#type = Some(header.r#type);
1914            let res = match header.r#type {
1915                1u16 => NdtpaAttrs::Ifindex({
1916                    let res = parse_u32(next);
1917                    let Some(val) = res else { break };
1918                    val
1919                }),
1920                2u16 => NdtpaAttrs::Refcnt({
1921                    let res = parse_u32(next);
1922                    let Some(val) = res else { break };
1923                    val
1924                }),
1925                3u16 => NdtpaAttrs::ReachableTime({
1926                    let res = parse_u64(next);
1927                    let Some(val) = res else { break };
1928                    val
1929                }),
1930                4u16 => NdtpaAttrs::BaseReachableTime({
1931                    let res = parse_u64(next);
1932                    let Some(val) = res else { break };
1933                    val
1934                }),
1935                5u16 => NdtpaAttrs::RetransTime({
1936                    let res = parse_u64(next);
1937                    let Some(val) = res else { break };
1938                    val
1939                }),
1940                6u16 => NdtpaAttrs::GcStaletime({
1941                    let res = parse_u64(next);
1942                    let Some(val) = res else { break };
1943                    val
1944                }),
1945                7u16 => NdtpaAttrs::DelayProbeTime({
1946                    let res = parse_u64(next);
1947                    let Some(val) = res else { break };
1948                    val
1949                }),
1950                8u16 => NdtpaAttrs::QueueLen({
1951                    let res = parse_u32(next);
1952                    let Some(val) = res else { break };
1953                    val
1954                }),
1955                9u16 => NdtpaAttrs::AppProbes({
1956                    let res = parse_u32(next);
1957                    let Some(val) = res else { break };
1958                    val
1959                }),
1960                10u16 => NdtpaAttrs::UcastProbes({
1961                    let res = parse_u32(next);
1962                    let Some(val) = res else { break };
1963                    val
1964                }),
1965                11u16 => NdtpaAttrs::McastProbes({
1966                    let res = parse_u32(next);
1967                    let Some(val) = res else { break };
1968                    val
1969                }),
1970                12u16 => NdtpaAttrs::AnycastDelay({
1971                    let res = parse_u64(next);
1972                    let Some(val) = res else { break };
1973                    val
1974                }),
1975                13u16 => NdtpaAttrs::ProxyDelay({
1976                    let res = parse_u64(next);
1977                    let Some(val) = res else { break };
1978                    val
1979                }),
1980                14u16 => NdtpaAttrs::ProxyQlen({
1981                    let res = parse_u32(next);
1982                    let Some(val) = res else { break };
1983                    val
1984                }),
1985                15u16 => NdtpaAttrs::Locktime({
1986                    let res = parse_u64(next);
1987                    let Some(val) = res else { break };
1988                    val
1989                }),
1990                16u16 => NdtpaAttrs::QueueLenbytes({
1991                    let res = parse_u32(next);
1992                    let Some(val) = res else { break };
1993                    val
1994                }),
1995                17u16 => NdtpaAttrs::McastReprobes({
1996                    let res = parse_u32(next);
1997                    let Some(val) = res else { break };
1998                    val
1999                }),
2000                18u16 => NdtpaAttrs::Pad({
2001                    let res = Some(next);
2002                    let Some(val) = res else { break };
2003                    val
2004                }),
2005                19u16 => NdtpaAttrs::IntervalProbeTimeMs({
2006                    let res = parse_u64(next);
2007                    let Some(val) = res else { break };
2008                    val
2009                }),
2010                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2011                n => continue,
2012            };
2013            return Some(Ok(res));
2014        }
2015        Some(Err(ErrorContext::new(
2016            "NdtpaAttrs",
2017            r#type.and_then(|t| NdtpaAttrs::attr_from_type(t)),
2018            self.orig_loc,
2019            self.buf.as_ptr().wrapping_add(pos) as usize,
2020        )))
2021    }
2022}
2023impl<'a> std::fmt::Debug for IterableNdtpaAttrs<'_> {
2024    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2025        let mut fmt = f.debug_struct("NdtpaAttrs");
2026        for attr in self.clone() {
2027            let attr = match attr {
2028                Ok(a) => a,
2029                Err(err) => {
2030                    fmt.finish()?;
2031                    f.write_str("Err(")?;
2032                    err.fmt(f)?;
2033                    return f.write_str(")");
2034                }
2035            };
2036            match attr {
2037                NdtpaAttrs::Ifindex(val) => fmt.field("Ifindex", &val),
2038                NdtpaAttrs::Refcnt(val) => fmt.field("Refcnt", &val),
2039                NdtpaAttrs::ReachableTime(val) => fmt.field("ReachableTime", &val),
2040                NdtpaAttrs::BaseReachableTime(val) => fmt.field("BaseReachableTime", &val),
2041                NdtpaAttrs::RetransTime(val) => fmt.field("RetransTime", &val),
2042                NdtpaAttrs::GcStaletime(val) => fmt.field("GcStaletime", &val),
2043                NdtpaAttrs::DelayProbeTime(val) => fmt.field("DelayProbeTime", &val),
2044                NdtpaAttrs::QueueLen(val) => fmt.field("QueueLen", &val),
2045                NdtpaAttrs::AppProbes(val) => fmt.field("AppProbes", &val),
2046                NdtpaAttrs::UcastProbes(val) => fmt.field("UcastProbes", &val),
2047                NdtpaAttrs::McastProbes(val) => fmt.field("McastProbes", &val),
2048                NdtpaAttrs::AnycastDelay(val) => fmt.field("AnycastDelay", &val),
2049                NdtpaAttrs::ProxyDelay(val) => fmt.field("ProxyDelay", &val),
2050                NdtpaAttrs::ProxyQlen(val) => fmt.field("ProxyQlen", &val),
2051                NdtpaAttrs::Locktime(val) => fmt.field("Locktime", &val),
2052                NdtpaAttrs::QueueLenbytes(val) => fmt.field("QueueLenbytes", &val),
2053                NdtpaAttrs::McastReprobes(val) => fmt.field("McastReprobes", &val),
2054                NdtpaAttrs::Pad(val) => fmt.field("Pad", &val),
2055                NdtpaAttrs::IntervalProbeTimeMs(val) => fmt.field("IntervalProbeTimeMs", &val),
2056            };
2057        }
2058        fmt.finish()
2059    }
2060}
2061impl IterableNdtpaAttrs<'_> {
2062    pub fn lookup_attr(
2063        &self,
2064        offset: usize,
2065        missing_type: Option<u16>,
2066    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2067        let mut stack = Vec::new();
2068        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2069        if missing_type.is_some() && cur == offset {
2070            stack.push(("NdtpaAttrs", offset));
2071            return (
2072                stack,
2073                missing_type.and_then(|t| NdtpaAttrs::attr_from_type(t)),
2074            );
2075        }
2076        if cur > offset || cur + self.buf.len() < offset {
2077            return (stack, None);
2078        }
2079        let mut attrs = self.clone();
2080        let mut last_off = cur + attrs.pos;
2081        while let Some(attr) = attrs.next() {
2082            let Ok(attr) = attr else { break };
2083            match attr {
2084                NdtpaAttrs::Ifindex(val) => {
2085                    if last_off == offset {
2086                        stack.push(("Ifindex", last_off));
2087                        break;
2088                    }
2089                }
2090                NdtpaAttrs::Refcnt(val) => {
2091                    if last_off == offset {
2092                        stack.push(("Refcnt", last_off));
2093                        break;
2094                    }
2095                }
2096                NdtpaAttrs::ReachableTime(val) => {
2097                    if last_off == offset {
2098                        stack.push(("ReachableTime", last_off));
2099                        break;
2100                    }
2101                }
2102                NdtpaAttrs::BaseReachableTime(val) => {
2103                    if last_off == offset {
2104                        stack.push(("BaseReachableTime", last_off));
2105                        break;
2106                    }
2107                }
2108                NdtpaAttrs::RetransTime(val) => {
2109                    if last_off == offset {
2110                        stack.push(("RetransTime", last_off));
2111                        break;
2112                    }
2113                }
2114                NdtpaAttrs::GcStaletime(val) => {
2115                    if last_off == offset {
2116                        stack.push(("GcStaletime", last_off));
2117                        break;
2118                    }
2119                }
2120                NdtpaAttrs::DelayProbeTime(val) => {
2121                    if last_off == offset {
2122                        stack.push(("DelayProbeTime", last_off));
2123                        break;
2124                    }
2125                }
2126                NdtpaAttrs::QueueLen(val) => {
2127                    if last_off == offset {
2128                        stack.push(("QueueLen", last_off));
2129                        break;
2130                    }
2131                }
2132                NdtpaAttrs::AppProbes(val) => {
2133                    if last_off == offset {
2134                        stack.push(("AppProbes", last_off));
2135                        break;
2136                    }
2137                }
2138                NdtpaAttrs::UcastProbes(val) => {
2139                    if last_off == offset {
2140                        stack.push(("UcastProbes", last_off));
2141                        break;
2142                    }
2143                }
2144                NdtpaAttrs::McastProbes(val) => {
2145                    if last_off == offset {
2146                        stack.push(("McastProbes", last_off));
2147                        break;
2148                    }
2149                }
2150                NdtpaAttrs::AnycastDelay(val) => {
2151                    if last_off == offset {
2152                        stack.push(("AnycastDelay", last_off));
2153                        break;
2154                    }
2155                }
2156                NdtpaAttrs::ProxyDelay(val) => {
2157                    if last_off == offset {
2158                        stack.push(("ProxyDelay", last_off));
2159                        break;
2160                    }
2161                }
2162                NdtpaAttrs::ProxyQlen(val) => {
2163                    if last_off == offset {
2164                        stack.push(("ProxyQlen", last_off));
2165                        break;
2166                    }
2167                }
2168                NdtpaAttrs::Locktime(val) => {
2169                    if last_off == offset {
2170                        stack.push(("Locktime", last_off));
2171                        break;
2172                    }
2173                }
2174                NdtpaAttrs::QueueLenbytes(val) => {
2175                    if last_off == offset {
2176                        stack.push(("QueueLenbytes", last_off));
2177                        break;
2178                    }
2179                }
2180                NdtpaAttrs::McastReprobes(val) => {
2181                    if last_off == offset {
2182                        stack.push(("McastReprobes", last_off));
2183                        break;
2184                    }
2185                }
2186                NdtpaAttrs::Pad(val) => {
2187                    if last_off == offset {
2188                        stack.push(("Pad", last_off));
2189                        break;
2190                    }
2191                }
2192                NdtpaAttrs::IntervalProbeTimeMs(val) => {
2193                    if last_off == offset {
2194                        stack.push(("IntervalProbeTimeMs", last_off));
2195                        break;
2196                    }
2197                }
2198                _ => {}
2199            };
2200            last_off = cur + attrs.pos;
2201        }
2202        if !stack.is_empty() {
2203            stack.push(("NdtpaAttrs", cur));
2204        }
2205        (stack, None)
2206    }
2207}
2208pub struct PushNeighbourAttrs<Prev: Rec> {
2209    pub(crate) prev: Option<Prev>,
2210    pub(crate) header_offset: Option<usize>,
2211}
2212impl<Prev: Rec> Rec for PushNeighbourAttrs<Prev> {
2213    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2214        self.prev.as_mut().unwrap().as_rec_mut()
2215    }
2216    fn as_rec(&self) -> &Vec<u8> {
2217        self.prev.as_ref().unwrap().as_rec()
2218    }
2219}
2220impl<Prev: Rec> PushNeighbourAttrs<Prev> {
2221    pub fn new(prev: Prev) -> Self {
2222        Self {
2223            prev: Some(prev),
2224            header_offset: None,
2225        }
2226    }
2227    pub fn end_nested(mut self) -> Prev {
2228        let mut prev = self.prev.take().unwrap();
2229        if let Some(header_offset) = &self.header_offset {
2230            finalize_nested_header(prev.as_rec_mut(), *header_offset);
2231        }
2232        prev
2233    }
2234    pub fn push_unspec(mut self, value: &[u8]) -> Self {
2235        push_header(self.as_rec_mut(), 0u16, value.len() as u16);
2236        self.as_rec_mut().extend(value);
2237        self
2238    }
2239    pub fn push_dst(mut self, value: std::net::IpAddr) -> Self {
2240        push_header(self.as_rec_mut(), 1u16, {
2241            match &value {
2242                IpAddr::V4(_) => 4,
2243                IpAddr::V6(_) => 16,
2244            }
2245        } as u16);
2246        encode_ip(self.as_rec_mut(), value);
2247        self
2248    }
2249    pub fn push_lladdr(mut self, value: &[u8]) -> Self {
2250        push_header(self.as_rec_mut(), 2u16, value.len() as u16);
2251        self.as_rec_mut().extend(value);
2252        self
2253    }
2254    pub fn push_cacheinfo(mut self, value: NdaCacheinfo) -> Self {
2255        push_header(self.as_rec_mut(), 3u16, value.as_slice().len() as u16);
2256        self.as_rec_mut().extend(value.as_slice());
2257        self
2258    }
2259    pub fn push_probes(mut self, value: u32) -> Self {
2260        push_header(self.as_rec_mut(), 4u16, 4 as u16);
2261        self.as_rec_mut().extend(value.to_ne_bytes());
2262        self
2263    }
2264    pub fn push_vlan(mut self, value: u16) -> Self {
2265        push_header(self.as_rec_mut(), 5u16, 2 as u16);
2266        self.as_rec_mut().extend(value.to_ne_bytes());
2267        self
2268    }
2269    pub fn push_port(mut self, value: u16) -> Self {
2270        push_header(self.as_rec_mut(), 6u16, 2 as u16);
2271        self.as_rec_mut().extend(value.to_ne_bytes());
2272        self
2273    }
2274    pub fn push_vni(mut self, value: u32) -> Self {
2275        push_header(self.as_rec_mut(), 7u16, 4 as u16);
2276        self.as_rec_mut().extend(value.to_ne_bytes());
2277        self
2278    }
2279    pub fn push_ifindex(mut self, value: u32) -> Self {
2280        push_header(self.as_rec_mut(), 8u16, 4 as u16);
2281        self.as_rec_mut().extend(value.to_ne_bytes());
2282        self
2283    }
2284    pub fn push_master(mut self, value: u32) -> Self {
2285        push_header(self.as_rec_mut(), 9u16, 4 as u16);
2286        self.as_rec_mut().extend(value.to_ne_bytes());
2287        self
2288    }
2289    pub fn push_link_netnsid(mut self, value: i32) -> Self {
2290        push_header(self.as_rec_mut(), 10u16, 4 as u16);
2291        self.as_rec_mut().extend(value.to_ne_bytes());
2292        self
2293    }
2294    pub fn push_src_vni(mut self, value: u32) -> Self {
2295        push_header(self.as_rec_mut(), 11u16, 4 as u16);
2296        self.as_rec_mut().extend(value.to_ne_bytes());
2297        self
2298    }
2299    pub fn push_protocol(mut self, value: u8) -> Self {
2300        push_header(self.as_rec_mut(), 12u16, 1 as u16);
2301        self.as_rec_mut().extend(value.to_ne_bytes());
2302        self
2303    }
2304    pub fn push_nh_id(mut self, value: u32) -> Self {
2305        push_header(self.as_rec_mut(), 13u16, 4 as u16);
2306        self.as_rec_mut().extend(value.to_ne_bytes());
2307        self
2308    }
2309    pub fn push_fdb_ext_attrs(mut self, value: &[u8]) -> Self {
2310        push_header(self.as_rec_mut(), 14u16, value.len() as u16);
2311        self.as_rec_mut().extend(value);
2312        self
2313    }
2314    #[doc = "Associated type: [`NtfExtFlags`] (enum)"]
2315    pub fn push_flags_ext(mut self, value: u32) -> Self {
2316        push_header(self.as_rec_mut(), 15u16, 4 as u16);
2317        self.as_rec_mut().extend(value.to_ne_bytes());
2318        self
2319    }
2320    pub fn push_ndm_state_mask(mut self, value: u16) -> Self {
2321        push_header(self.as_rec_mut(), 16u16, 2 as u16);
2322        self.as_rec_mut().extend(value.to_ne_bytes());
2323        self
2324    }
2325    pub fn push_ndm_flags_mask(mut self, value: u8) -> Self {
2326        push_header(self.as_rec_mut(), 17u16, 1 as u16);
2327        self.as_rec_mut().extend(value.to_ne_bytes());
2328        self
2329    }
2330}
2331impl<Prev: Rec> Drop for PushNeighbourAttrs<Prev> {
2332    fn drop(&mut self) {
2333        if let Some(prev) = &mut self.prev {
2334            if let Some(header_offset) = &self.header_offset {
2335                finalize_nested_header(prev.as_rec_mut(), *header_offset);
2336            }
2337        }
2338    }
2339}
2340pub struct PushNdtAttrs<Prev: Rec> {
2341    pub(crate) prev: Option<Prev>,
2342    pub(crate) header_offset: Option<usize>,
2343}
2344impl<Prev: Rec> Rec for PushNdtAttrs<Prev> {
2345    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2346        self.prev.as_mut().unwrap().as_rec_mut()
2347    }
2348    fn as_rec(&self) -> &Vec<u8> {
2349        self.prev.as_ref().unwrap().as_rec()
2350    }
2351}
2352impl<Prev: Rec> PushNdtAttrs<Prev> {
2353    pub fn new(prev: Prev) -> Self {
2354        Self {
2355            prev: Some(prev),
2356            header_offset: None,
2357        }
2358    }
2359    pub fn end_nested(mut self) -> Prev {
2360        let mut prev = self.prev.take().unwrap();
2361        if let Some(header_offset) = &self.header_offset {
2362            finalize_nested_header(prev.as_rec_mut(), *header_offset);
2363        }
2364        prev
2365    }
2366    pub fn push_name(mut self, value: &CStr) -> Self {
2367        push_header(
2368            self.as_rec_mut(),
2369            1u16,
2370            value.to_bytes_with_nul().len() as u16,
2371        );
2372        self.as_rec_mut().extend(value.to_bytes_with_nul());
2373        self
2374    }
2375    pub fn push_name_bytes(mut self, value: &[u8]) -> Self {
2376        push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
2377        self.as_rec_mut().extend(value);
2378        self.as_rec_mut().push(0);
2379        self
2380    }
2381    pub fn push_thresh1(mut self, value: u32) -> Self {
2382        push_header(self.as_rec_mut(), 2u16, 4 as u16);
2383        self.as_rec_mut().extend(value.to_ne_bytes());
2384        self
2385    }
2386    pub fn push_thresh2(mut self, value: u32) -> Self {
2387        push_header(self.as_rec_mut(), 3u16, 4 as u16);
2388        self.as_rec_mut().extend(value.to_ne_bytes());
2389        self
2390    }
2391    pub fn push_thresh3(mut self, value: u32) -> Self {
2392        push_header(self.as_rec_mut(), 4u16, 4 as u16);
2393        self.as_rec_mut().extend(value.to_ne_bytes());
2394        self
2395    }
2396    pub fn push_config(mut self, value: NdtConfig) -> Self {
2397        push_header(self.as_rec_mut(), 5u16, value.as_slice().len() as u16);
2398        self.as_rec_mut().extend(value.as_slice());
2399        self
2400    }
2401    pub fn nested_parms(mut self) -> PushNdtpaAttrs<Self> {
2402        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
2403        PushNdtpaAttrs {
2404            prev: Some(self),
2405            header_offset: Some(header_offset),
2406        }
2407    }
2408    pub fn push_stats(mut self, value: NdtStats) -> Self {
2409        push_header(self.as_rec_mut(), 7u16, value.as_slice().len() as u16);
2410        self.as_rec_mut().extend(value.as_slice());
2411        self
2412    }
2413    pub fn push_gc_interval(mut self, value: u64) -> Self {
2414        push_header(self.as_rec_mut(), 8u16, 8 as u16);
2415        self.as_rec_mut().extend(value.to_ne_bytes());
2416        self
2417    }
2418    pub fn push_pad(mut self, value: &[u8]) -> Self {
2419        push_header(self.as_rec_mut(), 9u16, value.len() as u16);
2420        self.as_rec_mut().extend(value);
2421        self
2422    }
2423}
2424impl<Prev: Rec> Drop for PushNdtAttrs<Prev> {
2425    fn drop(&mut self) {
2426        if let Some(prev) = &mut self.prev {
2427            if let Some(header_offset) = &self.header_offset {
2428                finalize_nested_header(prev.as_rec_mut(), *header_offset);
2429            }
2430        }
2431    }
2432}
2433pub struct PushNdtpaAttrs<Prev: Rec> {
2434    pub(crate) prev: Option<Prev>,
2435    pub(crate) header_offset: Option<usize>,
2436}
2437impl<Prev: Rec> Rec for PushNdtpaAttrs<Prev> {
2438    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2439        self.prev.as_mut().unwrap().as_rec_mut()
2440    }
2441    fn as_rec(&self) -> &Vec<u8> {
2442        self.prev.as_ref().unwrap().as_rec()
2443    }
2444}
2445impl<Prev: Rec> PushNdtpaAttrs<Prev> {
2446    pub fn new(prev: Prev) -> Self {
2447        Self {
2448            prev: Some(prev),
2449            header_offset: None,
2450        }
2451    }
2452    pub fn end_nested(mut self) -> Prev {
2453        let mut prev = self.prev.take().unwrap();
2454        if let Some(header_offset) = &self.header_offset {
2455            finalize_nested_header(prev.as_rec_mut(), *header_offset);
2456        }
2457        prev
2458    }
2459    pub fn push_ifindex(mut self, value: u32) -> Self {
2460        push_header(self.as_rec_mut(), 1u16, 4 as u16);
2461        self.as_rec_mut().extend(value.to_ne_bytes());
2462        self
2463    }
2464    pub fn push_refcnt(mut self, value: u32) -> Self {
2465        push_header(self.as_rec_mut(), 2u16, 4 as u16);
2466        self.as_rec_mut().extend(value.to_ne_bytes());
2467        self
2468    }
2469    pub fn push_reachable_time(mut self, value: u64) -> Self {
2470        push_header(self.as_rec_mut(), 3u16, 8 as u16);
2471        self.as_rec_mut().extend(value.to_ne_bytes());
2472        self
2473    }
2474    pub fn push_base_reachable_time(mut self, value: u64) -> Self {
2475        push_header(self.as_rec_mut(), 4u16, 8 as u16);
2476        self.as_rec_mut().extend(value.to_ne_bytes());
2477        self
2478    }
2479    pub fn push_retrans_time(mut self, value: u64) -> Self {
2480        push_header(self.as_rec_mut(), 5u16, 8 as u16);
2481        self.as_rec_mut().extend(value.to_ne_bytes());
2482        self
2483    }
2484    pub fn push_gc_staletime(mut self, value: u64) -> Self {
2485        push_header(self.as_rec_mut(), 6u16, 8 as u16);
2486        self.as_rec_mut().extend(value.to_ne_bytes());
2487        self
2488    }
2489    pub fn push_delay_probe_time(mut self, value: u64) -> Self {
2490        push_header(self.as_rec_mut(), 7u16, 8 as u16);
2491        self.as_rec_mut().extend(value.to_ne_bytes());
2492        self
2493    }
2494    pub fn push_queue_len(mut self, value: u32) -> Self {
2495        push_header(self.as_rec_mut(), 8u16, 4 as u16);
2496        self.as_rec_mut().extend(value.to_ne_bytes());
2497        self
2498    }
2499    pub fn push_app_probes(mut self, value: u32) -> Self {
2500        push_header(self.as_rec_mut(), 9u16, 4 as u16);
2501        self.as_rec_mut().extend(value.to_ne_bytes());
2502        self
2503    }
2504    pub fn push_ucast_probes(mut self, value: u32) -> Self {
2505        push_header(self.as_rec_mut(), 10u16, 4 as u16);
2506        self.as_rec_mut().extend(value.to_ne_bytes());
2507        self
2508    }
2509    pub fn push_mcast_probes(mut self, value: u32) -> Self {
2510        push_header(self.as_rec_mut(), 11u16, 4 as u16);
2511        self.as_rec_mut().extend(value.to_ne_bytes());
2512        self
2513    }
2514    pub fn push_anycast_delay(mut self, value: u64) -> Self {
2515        push_header(self.as_rec_mut(), 12u16, 8 as u16);
2516        self.as_rec_mut().extend(value.to_ne_bytes());
2517        self
2518    }
2519    pub fn push_proxy_delay(mut self, value: u64) -> Self {
2520        push_header(self.as_rec_mut(), 13u16, 8 as u16);
2521        self.as_rec_mut().extend(value.to_ne_bytes());
2522        self
2523    }
2524    pub fn push_proxy_qlen(mut self, value: u32) -> Self {
2525        push_header(self.as_rec_mut(), 14u16, 4 as u16);
2526        self.as_rec_mut().extend(value.to_ne_bytes());
2527        self
2528    }
2529    pub fn push_locktime(mut self, value: u64) -> Self {
2530        push_header(self.as_rec_mut(), 15u16, 8 as u16);
2531        self.as_rec_mut().extend(value.to_ne_bytes());
2532        self
2533    }
2534    pub fn push_queue_lenbytes(mut self, value: u32) -> Self {
2535        push_header(self.as_rec_mut(), 16u16, 4 as u16);
2536        self.as_rec_mut().extend(value.to_ne_bytes());
2537        self
2538    }
2539    pub fn push_mcast_reprobes(mut self, value: u32) -> Self {
2540        push_header(self.as_rec_mut(), 17u16, 4 as u16);
2541        self.as_rec_mut().extend(value.to_ne_bytes());
2542        self
2543    }
2544    pub fn push_pad(mut self, value: &[u8]) -> Self {
2545        push_header(self.as_rec_mut(), 18u16, value.len() as u16);
2546        self.as_rec_mut().extend(value);
2547        self
2548    }
2549    pub fn push_interval_probe_time_ms(mut self, value: u64) -> Self {
2550        push_header(self.as_rec_mut(), 19u16, 8 as u16);
2551        self.as_rec_mut().extend(value.to_ne_bytes());
2552        self
2553    }
2554}
2555impl<Prev: Rec> Drop for PushNdtpaAttrs<Prev> {
2556    fn drop(&mut self) {
2557        if let Some(prev) = &mut self.prev {
2558            if let Some(header_offset) = &self.header_offset {
2559                finalize_nested_header(prev.as_rec_mut(), *header_offset);
2560            }
2561        }
2562    }
2563}
2564#[doc = "Add new neighbour entry\nRequest attributes:\n- [.push_dst()](PushNeighbourAttrs::push_dst)\n- [.push_lladdr()](PushNeighbourAttrs::push_lladdr)\n- [.push_probes()](PushNeighbourAttrs::push_probes)\n- [.push_vlan()](PushNeighbourAttrs::push_vlan)\n- [.push_port()](PushNeighbourAttrs::push_port)\n- [.push_vni()](PushNeighbourAttrs::push_vni)\n- [.push_ifindex()](PushNeighbourAttrs::push_ifindex)\n- [.push_master()](PushNeighbourAttrs::push_master)\n- [.push_protocol()](PushNeighbourAttrs::push_protocol)\n- [.push_nh_id()](PushNeighbourAttrs::push_nh_id)\n- [.push_fdb_ext_attrs()](PushNeighbourAttrs::push_fdb_ext_attrs)\n- [.push_flags_ext()](PushNeighbourAttrs::push_flags_ext)\n"]
2565#[derive(Debug)]
2566pub struct OpNewneighDo<'r> {
2567    request: Request<'r>,
2568}
2569impl<'r> OpNewneighDo<'r> {
2570    pub fn new(mut request: Request<'r>, header: &Ndmsg) -> Self {
2571        Self::write_header(request.buf_mut(), header);
2572        Self { request: request }
2573    }
2574    pub fn encode_request<'buf>(
2575        buf: &'buf mut Vec<u8>,
2576        header: &Ndmsg,
2577    ) -> PushNeighbourAttrs<&'buf mut Vec<u8>> {
2578        Self::write_header(buf, header);
2579        PushNeighbourAttrs::new(buf)
2580    }
2581    pub fn encode(&mut self) -> PushNeighbourAttrs<&mut Vec<u8>> {
2582        PushNeighbourAttrs::new(self.request.buf_mut())
2583    }
2584    pub fn into_encoder(self) -> PushNeighbourAttrs<RequestBuf<'r>> {
2585        PushNeighbourAttrs::new(self.request.buf)
2586    }
2587    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndmsg, IterableNeighbourAttrs<'a>) {
2588        let (header, attrs) = buf.split_at(buf.len().min(Ndmsg::len()));
2589        (
2590            Ndmsg::new_from_slice(header).unwrap_or_default(),
2591            IterableNeighbourAttrs::with_loc(attrs, buf.as_ptr() as usize),
2592        )
2593    }
2594    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ndmsg) {
2595        prev.as_rec_mut().extend(header.as_slice());
2596    }
2597}
2598impl NetlinkRequest for OpNewneighDo<'_> {
2599    fn protocol(&self) -> Protocol {
2600        Protocol::Raw {
2601            protonum: 0u16,
2602            request_type: 28u16,
2603        }
2604    }
2605    fn flags(&self) -> u16 {
2606        self.request.flags
2607    }
2608    fn payload(&self) -> &[u8] {
2609        self.request.buf()
2610    }
2611    type ReplyType<'buf> = (Ndmsg, IterableNeighbourAttrs<'buf>);
2612    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2613        Self::decode_request(buf)
2614    }
2615    fn lookup(
2616        buf: &[u8],
2617        offset: usize,
2618        missing_type: Option<u16>,
2619    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2620        Self::decode_request(buf)
2621            .1
2622            .lookup_attr(offset, missing_type)
2623    }
2624}
2625#[doc = "Remove an existing neighbour entry\nRequest attributes:\n- [.push_dst()](PushNeighbourAttrs::push_dst)\n- [.push_ifindex()](PushNeighbourAttrs::push_ifindex)\n"]
2626#[derive(Debug)]
2627pub struct OpDelneighDo<'r> {
2628    request: Request<'r>,
2629}
2630impl<'r> OpDelneighDo<'r> {
2631    pub fn new(mut request: Request<'r>, header: &Ndmsg) -> Self {
2632        Self::write_header(request.buf_mut(), header);
2633        Self { request: request }
2634    }
2635    pub fn encode_request<'buf>(
2636        buf: &'buf mut Vec<u8>,
2637        header: &Ndmsg,
2638    ) -> PushNeighbourAttrs<&'buf mut Vec<u8>> {
2639        Self::write_header(buf, header);
2640        PushNeighbourAttrs::new(buf)
2641    }
2642    pub fn encode(&mut self) -> PushNeighbourAttrs<&mut Vec<u8>> {
2643        PushNeighbourAttrs::new(self.request.buf_mut())
2644    }
2645    pub fn into_encoder(self) -> PushNeighbourAttrs<RequestBuf<'r>> {
2646        PushNeighbourAttrs::new(self.request.buf)
2647    }
2648    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndmsg, IterableNeighbourAttrs<'a>) {
2649        let (header, attrs) = buf.split_at(buf.len().min(Ndmsg::len()));
2650        (
2651            Ndmsg::new_from_slice(header).unwrap_or_default(),
2652            IterableNeighbourAttrs::with_loc(attrs, buf.as_ptr() as usize),
2653        )
2654    }
2655    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ndmsg) {
2656        prev.as_rec_mut().extend(header.as_slice());
2657    }
2658}
2659impl NetlinkRequest for OpDelneighDo<'_> {
2660    fn protocol(&self) -> Protocol {
2661        Protocol::Raw {
2662            protonum: 0u16,
2663            request_type: 29u16,
2664        }
2665    }
2666    fn flags(&self) -> u16 {
2667        self.request.flags
2668    }
2669    fn payload(&self) -> &[u8] {
2670        self.request.buf()
2671    }
2672    type ReplyType<'buf> = (Ndmsg, IterableNeighbourAttrs<'buf>);
2673    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2674        Self::decode_request(buf)
2675    }
2676    fn lookup(
2677        buf: &[u8],
2678        offset: usize,
2679        missing_type: Option<u16>,
2680    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2681        Self::decode_request(buf)
2682            .1
2683            .lookup_attr(offset, missing_type)
2684    }
2685}
2686#[doc = "Get or dump neighbour entries\nRequest attributes:\n- [.push_ifindex()](PushNeighbourAttrs::push_ifindex)\n- [.push_master()](PushNeighbourAttrs::push_master)\n\nReply attributes:\n- [.get_dst()](IterableNeighbourAttrs::get_dst)\n- [.get_lladdr()](IterableNeighbourAttrs::get_lladdr)\n- [.get_probes()](IterableNeighbourAttrs::get_probes)\n- [.get_vlan()](IterableNeighbourAttrs::get_vlan)\n- [.get_port()](IterableNeighbourAttrs::get_port)\n- [.get_vni()](IterableNeighbourAttrs::get_vni)\n- [.get_ifindex()](IterableNeighbourAttrs::get_ifindex)\n- [.get_master()](IterableNeighbourAttrs::get_master)\n- [.get_protocol()](IterableNeighbourAttrs::get_protocol)\n- [.get_nh_id()](IterableNeighbourAttrs::get_nh_id)\n- [.get_fdb_ext_attrs()](IterableNeighbourAttrs::get_fdb_ext_attrs)\n- [.get_flags_ext()](IterableNeighbourAttrs::get_flags_ext)\n"]
2687#[derive(Debug)]
2688pub struct OpGetneighDump<'r> {
2689    request: Request<'r>,
2690}
2691impl<'r> OpGetneighDump<'r> {
2692    pub fn new(mut request: Request<'r>, header: &Ndmsg) -> Self {
2693        Self::write_header(request.buf_mut(), header);
2694        Self {
2695            request: request.set_dump(),
2696        }
2697    }
2698    pub fn encode_request<'buf>(
2699        buf: &'buf mut Vec<u8>,
2700        header: &Ndmsg,
2701    ) -> PushNeighbourAttrs<&'buf mut Vec<u8>> {
2702        Self::write_header(buf, header);
2703        PushNeighbourAttrs::new(buf)
2704    }
2705    pub fn encode(&mut self) -> PushNeighbourAttrs<&mut Vec<u8>> {
2706        PushNeighbourAttrs::new(self.request.buf_mut())
2707    }
2708    pub fn into_encoder(self) -> PushNeighbourAttrs<RequestBuf<'r>> {
2709        PushNeighbourAttrs::new(self.request.buf)
2710    }
2711    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndmsg, IterableNeighbourAttrs<'a>) {
2712        let (header, attrs) = buf.split_at(buf.len().min(Ndmsg::len()));
2713        (
2714            Ndmsg::new_from_slice(header).unwrap_or_default(),
2715            IterableNeighbourAttrs::with_loc(attrs, buf.as_ptr() as usize),
2716        )
2717    }
2718    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ndmsg) {
2719        prev.as_rec_mut().extend(header.as_slice());
2720    }
2721}
2722impl NetlinkRequest for OpGetneighDump<'_> {
2723    fn protocol(&self) -> Protocol {
2724        Protocol::Raw {
2725            protonum: 0u16,
2726            request_type: 30u16,
2727        }
2728    }
2729    fn flags(&self) -> u16 {
2730        self.request.flags
2731    }
2732    fn payload(&self) -> &[u8] {
2733        self.request.buf()
2734    }
2735    type ReplyType<'buf> = (Ndmsg, IterableNeighbourAttrs<'buf>);
2736    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2737        Self::decode_request(buf)
2738    }
2739    fn lookup(
2740        buf: &[u8],
2741        offset: usize,
2742        missing_type: Option<u16>,
2743    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2744        Self::decode_request(buf)
2745            .1
2746            .lookup_attr(offset, missing_type)
2747    }
2748}
2749#[doc = "Get or dump neighbour entries\nRequest attributes:\n- [.push_dst()](PushNeighbourAttrs::push_dst)\n\nReply attributes:\n- [.get_dst()](IterableNeighbourAttrs::get_dst)\n- [.get_lladdr()](IterableNeighbourAttrs::get_lladdr)\n- [.get_probes()](IterableNeighbourAttrs::get_probes)\n- [.get_vlan()](IterableNeighbourAttrs::get_vlan)\n- [.get_port()](IterableNeighbourAttrs::get_port)\n- [.get_vni()](IterableNeighbourAttrs::get_vni)\n- [.get_ifindex()](IterableNeighbourAttrs::get_ifindex)\n- [.get_master()](IterableNeighbourAttrs::get_master)\n- [.get_protocol()](IterableNeighbourAttrs::get_protocol)\n- [.get_nh_id()](IterableNeighbourAttrs::get_nh_id)\n- [.get_fdb_ext_attrs()](IterableNeighbourAttrs::get_fdb_ext_attrs)\n- [.get_flags_ext()](IterableNeighbourAttrs::get_flags_ext)\n"]
2750#[derive(Debug)]
2751pub struct OpGetneighDo<'r> {
2752    request: Request<'r>,
2753}
2754impl<'r> OpGetneighDo<'r> {
2755    pub fn new(mut request: Request<'r>, header: &Ndmsg) -> Self {
2756        Self::write_header(request.buf_mut(), header);
2757        Self { request: request }
2758    }
2759    pub fn encode_request<'buf>(
2760        buf: &'buf mut Vec<u8>,
2761        header: &Ndmsg,
2762    ) -> PushNeighbourAttrs<&'buf mut Vec<u8>> {
2763        Self::write_header(buf, header);
2764        PushNeighbourAttrs::new(buf)
2765    }
2766    pub fn encode(&mut self) -> PushNeighbourAttrs<&mut Vec<u8>> {
2767        PushNeighbourAttrs::new(self.request.buf_mut())
2768    }
2769    pub fn into_encoder(self) -> PushNeighbourAttrs<RequestBuf<'r>> {
2770        PushNeighbourAttrs::new(self.request.buf)
2771    }
2772    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndmsg, IterableNeighbourAttrs<'a>) {
2773        let (header, attrs) = buf.split_at(buf.len().min(Ndmsg::len()));
2774        (
2775            Ndmsg::new_from_slice(header).unwrap_or_default(),
2776            IterableNeighbourAttrs::with_loc(attrs, buf.as_ptr() as usize),
2777        )
2778    }
2779    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ndmsg) {
2780        prev.as_rec_mut().extend(header.as_slice());
2781    }
2782}
2783impl NetlinkRequest for OpGetneighDo<'_> {
2784    fn protocol(&self) -> Protocol {
2785        Protocol::Raw {
2786            protonum: 0u16,
2787            request_type: 30u16,
2788        }
2789    }
2790    fn flags(&self) -> u16 {
2791        self.request.flags
2792    }
2793    fn payload(&self) -> &[u8] {
2794        self.request.buf()
2795    }
2796    type ReplyType<'buf> = (Ndmsg, IterableNeighbourAttrs<'buf>);
2797    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2798        Self::decode_request(buf)
2799    }
2800    fn lookup(
2801        buf: &[u8],
2802        offset: usize,
2803        missing_type: Option<u16>,
2804    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2805        Self::decode_request(buf)
2806            .1
2807            .lookup_attr(offset, missing_type)
2808    }
2809}
2810#[doc = "Get or dump neighbour tables\n\nReply attributes:\n- [.get_name()](IterableNdtAttrs::get_name)\n- [.get_thresh1()](IterableNdtAttrs::get_thresh1)\n- [.get_thresh2()](IterableNdtAttrs::get_thresh2)\n- [.get_thresh3()](IterableNdtAttrs::get_thresh3)\n- [.get_config()](IterableNdtAttrs::get_config)\n- [.get_parms()](IterableNdtAttrs::get_parms)\n- [.get_stats()](IterableNdtAttrs::get_stats)\n- [.get_gc_interval()](IterableNdtAttrs::get_gc_interval)\n"]
2811#[derive(Debug)]
2812pub struct OpGetneightblDump<'r> {
2813    request: Request<'r>,
2814}
2815impl<'r> OpGetneightblDump<'r> {
2816    pub fn new(mut request: Request<'r>, header: &Ndtmsg) -> Self {
2817        Self::write_header(request.buf_mut(), header);
2818        Self {
2819            request: request.set_dump(),
2820        }
2821    }
2822    pub fn encode_request<'buf>(
2823        buf: &'buf mut Vec<u8>,
2824        header: &Ndtmsg,
2825    ) -> PushNdtAttrs<&'buf mut Vec<u8>> {
2826        Self::write_header(buf, header);
2827        PushNdtAttrs::new(buf)
2828    }
2829    pub fn encode(&mut self) -> PushNdtAttrs<&mut Vec<u8>> {
2830        PushNdtAttrs::new(self.request.buf_mut())
2831    }
2832    pub fn into_encoder(self) -> PushNdtAttrs<RequestBuf<'r>> {
2833        PushNdtAttrs::new(self.request.buf)
2834    }
2835    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndtmsg, IterableNdtAttrs<'a>) {
2836        let (header, attrs) = buf.split_at(buf.len().min(Ndtmsg::len()));
2837        (
2838            Ndtmsg::new_from_slice(header).unwrap_or_default(),
2839            IterableNdtAttrs::with_loc(attrs, buf.as_ptr() as usize),
2840        )
2841    }
2842    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ndtmsg) {
2843        prev.as_rec_mut().extend(header.as_slice());
2844    }
2845}
2846impl NetlinkRequest for OpGetneightblDump<'_> {
2847    fn protocol(&self) -> Protocol {
2848        Protocol::Raw {
2849            protonum: 0u16,
2850            request_type: 66u16,
2851        }
2852    }
2853    fn flags(&self) -> u16 {
2854        self.request.flags
2855    }
2856    fn payload(&self) -> &[u8] {
2857        self.request.buf()
2858    }
2859    type ReplyType<'buf> = (Ndtmsg, IterableNdtAttrs<'buf>);
2860    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2861        Self::decode_request(buf)
2862    }
2863    fn lookup(
2864        buf: &[u8],
2865        offset: usize,
2866        missing_type: Option<u16>,
2867    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2868        Self::decode_request(buf)
2869            .1
2870            .lookup_attr(offset, missing_type)
2871    }
2872}
2873#[doc = "Set neighbour tables\nRequest attributes:\n- [.push_name()](PushNdtAttrs::push_name)\n- [.push_thresh1()](PushNdtAttrs::push_thresh1)\n- [.push_thresh2()](PushNdtAttrs::push_thresh2)\n- [.push_thresh3()](PushNdtAttrs::push_thresh3)\n- [.nested_parms()](PushNdtAttrs::nested_parms)\n- [.push_gc_interval()](PushNdtAttrs::push_gc_interval)\n"]
2874#[derive(Debug)]
2875pub struct OpSetneightblDo<'r> {
2876    request: Request<'r>,
2877}
2878impl<'r> OpSetneightblDo<'r> {
2879    pub fn new(mut request: Request<'r>, header: &Ndtmsg) -> Self {
2880        Self::write_header(request.buf_mut(), header);
2881        Self { request: request }
2882    }
2883    pub fn encode_request<'buf>(
2884        buf: &'buf mut Vec<u8>,
2885        header: &Ndtmsg,
2886    ) -> PushNdtAttrs<&'buf mut Vec<u8>> {
2887        Self::write_header(buf, header);
2888        PushNdtAttrs::new(buf)
2889    }
2890    pub fn encode(&mut self) -> PushNdtAttrs<&mut Vec<u8>> {
2891        PushNdtAttrs::new(self.request.buf_mut())
2892    }
2893    pub fn into_encoder(self) -> PushNdtAttrs<RequestBuf<'r>> {
2894        PushNdtAttrs::new(self.request.buf)
2895    }
2896    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndtmsg, IterableNdtAttrs<'a>) {
2897        let (header, attrs) = buf.split_at(buf.len().min(Ndtmsg::len()));
2898        (
2899            Ndtmsg::new_from_slice(header).unwrap_or_default(),
2900            IterableNdtAttrs::with_loc(attrs, buf.as_ptr() as usize),
2901        )
2902    }
2903    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ndtmsg) {
2904        prev.as_rec_mut().extend(header.as_slice());
2905    }
2906}
2907impl NetlinkRequest for OpSetneightblDo<'_> {
2908    fn protocol(&self) -> Protocol {
2909        Protocol::Raw {
2910            protonum: 0u16,
2911            request_type: 67u16,
2912        }
2913    }
2914    fn flags(&self) -> u16 {
2915        self.request.flags
2916    }
2917    fn payload(&self) -> &[u8] {
2918        self.request.buf()
2919    }
2920    type ReplyType<'buf> = (Ndtmsg, IterableNdtAttrs<'buf>);
2921    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2922        Self::decode_request(buf)
2923    }
2924    fn lookup(
2925        buf: &[u8],
2926        offset: usize,
2927        missing_type: Option<u16>,
2928    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2929        Self::decode_request(buf)
2930            .1
2931            .lookup_attr(offset, missing_type)
2932    }
2933}
2934#[derive(Debug)]
2935pub struct ChainedFinal<'a> {
2936    inner: Chained<'a>,
2937}
2938#[derive(Debug)]
2939pub struct Chained<'a> {
2940    buf: RequestBuf<'a>,
2941    first_seq: u32,
2942    lookups: Vec<(&'static str, LookupFn)>,
2943    last_header_offset: usize,
2944    last_kind: Option<RequestInfo>,
2945}
2946impl<'a> ChainedFinal<'a> {
2947    pub fn into_chained(self) -> Chained<'a> {
2948        self.inner
2949    }
2950    pub fn buf(&self) -> &Vec<u8> {
2951        self.inner.buf()
2952    }
2953    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2954        self.inner.buf_mut()
2955    }
2956    fn get_index(&self, seq: u32) -> Option<u32> {
2957        let min = self.inner.first_seq;
2958        let max = min.wrapping_add(self.inner.lookups.len() as u32);
2959        return if min <= max {
2960            (min..max).contains(&seq).then(|| seq - min)
2961        } else if min <= seq {
2962            Some(seq - min)
2963        } else if seq < max {
2964            Some(u32::MAX - min + seq)
2965        } else {
2966            None
2967        };
2968    }
2969}
2970impl crate::traits::NetlinkChained for ChainedFinal<'_> {
2971    fn protonum(&self) -> u16 {
2972        PROTONUM
2973    }
2974    fn payload(&self) -> &[u8] {
2975        self.buf()
2976    }
2977    fn chain_len(&self) -> usize {
2978        self.inner.lookups.len()
2979    }
2980    fn get_index(&self, seq: u32) -> Option<usize> {
2981        self.get_index(seq).map(|n| n as usize)
2982    }
2983    fn name(&self, index: usize) -> &'static str {
2984        self.inner.lookups[index].0
2985    }
2986    fn lookup(&self, index: usize) -> LookupFn {
2987        self.inner.lookups[index].1
2988    }
2989}
2990impl Chained<'static> {
2991    pub fn new(first_seq: u32) -> Self {
2992        Self::new_from_buf(Vec::new(), first_seq)
2993    }
2994    pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
2995        Self {
2996            buf: RequestBuf::Own(buf),
2997            first_seq,
2998            lookups: Vec::new(),
2999            last_header_offset: 0,
3000            last_kind: None,
3001        }
3002    }
3003    pub fn into_buf(self) -> Vec<u8> {
3004        match self.buf {
3005            RequestBuf::Own(buf) => buf,
3006            _ => unreachable!(),
3007        }
3008    }
3009}
3010impl<'a> Chained<'a> {
3011    pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
3012        Self {
3013            buf: RequestBuf::Ref(buf),
3014            first_seq,
3015            lookups: Vec::new(),
3016            last_header_offset: 0,
3017            last_kind: None,
3018        }
3019    }
3020    pub fn finalize(mut self) -> ChainedFinal<'a> {
3021        self.update_header();
3022        ChainedFinal { inner: self }
3023    }
3024    pub fn request(&mut self) -> Request<'_> {
3025        self.update_header();
3026        self.last_header_offset = self.buf().len();
3027        self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
3028        let mut request = Request::new_extend(self.buf.buf_mut());
3029        self.last_kind = None;
3030        request.writeback = Some(&mut self.last_kind);
3031        request
3032    }
3033    pub fn buf(&self) -> &Vec<u8> {
3034        self.buf.buf()
3035    }
3036    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3037        self.buf.buf_mut()
3038    }
3039    fn update_header(&mut self) {
3040        let Some(RequestInfo {
3041            protocol,
3042            flags,
3043            name,
3044            lookup,
3045        }) = self.last_kind
3046        else {
3047            if !self.buf().is_empty() {
3048                assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
3049                self.buf.buf_mut().truncate(self.last_header_offset);
3050            }
3051            return;
3052        };
3053        let header_offset = self.last_header_offset;
3054        let request_type = match protocol {
3055            Protocol::Raw { request_type, .. } => request_type,
3056            Protocol::Generic(_) => unreachable!(),
3057        };
3058        let index = self.lookups.len();
3059        let seq = self.first_seq.wrapping_add(index as u32);
3060        self.lookups.push((name, lookup));
3061        let buf = self.buf_mut();
3062        align(buf);
3063        let header = Nlmsghdr {
3064            len: (buf.len() - header_offset) as u32,
3065            r#type: request_type,
3066            flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
3067            seq,
3068            pid: 0,
3069        };
3070        buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
3071    }
3072}
3073use crate::traits::LookupFn;
3074use crate::utils::RequestBuf;
3075#[derive(Debug)]
3076pub struct Request<'buf> {
3077    buf: RequestBuf<'buf>,
3078    flags: u16,
3079    writeback: Option<&'buf mut Option<RequestInfo>>,
3080}
3081#[allow(unused)]
3082#[derive(Debug, Clone)]
3083pub struct RequestInfo {
3084    protocol: Protocol,
3085    flags: u16,
3086    name: &'static str,
3087    lookup: LookupFn,
3088}
3089impl Request<'static> {
3090    pub fn new() -> Self {
3091        Self::new_from_buf(Vec::new())
3092    }
3093    pub fn new_from_buf(buf: Vec<u8>) -> Self {
3094        Self {
3095            flags: 0,
3096            buf: RequestBuf::Own(buf),
3097            writeback: None,
3098        }
3099    }
3100    pub fn into_buf(self) -> Vec<u8> {
3101        match self.buf {
3102            RequestBuf::Own(buf) => buf,
3103            _ => unreachable!(),
3104        }
3105    }
3106}
3107impl<'buf> Request<'buf> {
3108    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
3109        buf.clear();
3110        Self::new_extend(buf)
3111    }
3112    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
3113        Self {
3114            flags: 0,
3115            buf: RequestBuf::Ref(buf),
3116            writeback: None,
3117        }
3118    }
3119    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
3120        let Some(writeback) = &mut self.writeback else {
3121            return;
3122        };
3123        **writeback = Some(RequestInfo {
3124            protocol,
3125            flags: self.flags,
3126            name,
3127            lookup,
3128        })
3129    }
3130    pub fn buf(&self) -> &Vec<u8> {
3131        self.buf.buf()
3132    }
3133    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3134        self.buf.buf_mut()
3135    }
3136    #[doc = "Set `NLM_F_CREATE` flag"]
3137    pub fn set_create(mut self) -> Self {
3138        self.flags |= consts::NLM_F_CREATE as u16;
3139        self
3140    }
3141    #[doc = "Set `NLM_F_EXCL` flag"]
3142    pub fn set_excl(mut self) -> Self {
3143        self.flags |= consts::NLM_F_EXCL as u16;
3144        self
3145    }
3146    #[doc = "Set `NLM_F_REPLACE` flag"]
3147    pub fn set_replace(mut self) -> Self {
3148        self.flags |= consts::NLM_F_REPLACE as u16;
3149        self
3150    }
3151    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
3152    pub fn set_change(self) -> Self {
3153        self.set_create().set_replace()
3154    }
3155    #[doc = "Set `NLM_F_APPEND` flag"]
3156    pub fn set_append(mut self) -> Self {
3157        self.flags |= consts::NLM_F_APPEND as u16;
3158        self
3159    }
3160    #[doc = "Set `self.flags |= flags`"]
3161    pub fn set_flags(mut self, flags: u16) -> Self {
3162        self.flags |= flags;
3163        self
3164    }
3165    #[doc = "Set `self.flags ^= self.flags & flags`"]
3166    pub fn unset_flags(mut self, flags: u16) -> Self {
3167        self.flags ^= self.flags & flags;
3168        self
3169    }
3170    #[doc = "Set `NLM_F_DUMP` flag"]
3171    fn set_dump(mut self) -> Self {
3172        self.flags |= consts::NLM_F_DUMP as u16;
3173        self
3174    }
3175    #[doc = "Add new neighbour entry\nRequest attributes:\n- [.push_dst()](PushNeighbourAttrs::push_dst)\n- [.push_lladdr()](PushNeighbourAttrs::push_lladdr)\n- [.push_probes()](PushNeighbourAttrs::push_probes)\n- [.push_vlan()](PushNeighbourAttrs::push_vlan)\n- [.push_port()](PushNeighbourAttrs::push_port)\n- [.push_vni()](PushNeighbourAttrs::push_vni)\n- [.push_ifindex()](PushNeighbourAttrs::push_ifindex)\n- [.push_master()](PushNeighbourAttrs::push_master)\n- [.push_protocol()](PushNeighbourAttrs::push_protocol)\n- [.push_nh_id()](PushNeighbourAttrs::push_nh_id)\n- [.push_fdb_ext_attrs()](PushNeighbourAttrs::push_fdb_ext_attrs)\n- [.push_flags_ext()](PushNeighbourAttrs::push_flags_ext)\n"]
3176    pub fn op_newneigh_do(self, header: &Ndmsg) -> OpNewneighDo<'buf> {
3177        let mut res = OpNewneighDo::new(self, header);
3178        res.request
3179            .do_writeback(res.protocol(), "op-newneigh-do", OpNewneighDo::lookup);
3180        res
3181    }
3182    #[doc = "Remove an existing neighbour entry\nRequest attributes:\n- [.push_dst()](PushNeighbourAttrs::push_dst)\n- [.push_ifindex()](PushNeighbourAttrs::push_ifindex)\n"]
3183    pub fn op_delneigh_do(self, header: &Ndmsg) -> OpDelneighDo<'buf> {
3184        let mut res = OpDelneighDo::new(self, header);
3185        res.request
3186            .do_writeback(res.protocol(), "op-delneigh-do", OpDelneighDo::lookup);
3187        res
3188    }
3189    #[doc = "Get or dump neighbour entries\nRequest attributes:\n- [.push_ifindex()](PushNeighbourAttrs::push_ifindex)\n- [.push_master()](PushNeighbourAttrs::push_master)\n\nReply attributes:\n- [.get_dst()](IterableNeighbourAttrs::get_dst)\n- [.get_lladdr()](IterableNeighbourAttrs::get_lladdr)\n- [.get_probes()](IterableNeighbourAttrs::get_probes)\n- [.get_vlan()](IterableNeighbourAttrs::get_vlan)\n- [.get_port()](IterableNeighbourAttrs::get_port)\n- [.get_vni()](IterableNeighbourAttrs::get_vni)\n- [.get_ifindex()](IterableNeighbourAttrs::get_ifindex)\n- [.get_master()](IterableNeighbourAttrs::get_master)\n- [.get_protocol()](IterableNeighbourAttrs::get_protocol)\n- [.get_nh_id()](IterableNeighbourAttrs::get_nh_id)\n- [.get_fdb_ext_attrs()](IterableNeighbourAttrs::get_fdb_ext_attrs)\n- [.get_flags_ext()](IterableNeighbourAttrs::get_flags_ext)\n"]
3190    pub fn op_getneigh_dump(self, header: &Ndmsg) -> OpGetneighDump<'buf> {
3191        let mut res = OpGetneighDump::new(self, header);
3192        res.request
3193            .do_writeback(res.protocol(), "op-getneigh-dump", OpGetneighDump::lookup);
3194        res
3195    }
3196    #[doc = "Get or dump neighbour entries\nRequest attributes:\n- [.push_dst()](PushNeighbourAttrs::push_dst)\n\nReply attributes:\n- [.get_dst()](IterableNeighbourAttrs::get_dst)\n- [.get_lladdr()](IterableNeighbourAttrs::get_lladdr)\n- [.get_probes()](IterableNeighbourAttrs::get_probes)\n- [.get_vlan()](IterableNeighbourAttrs::get_vlan)\n- [.get_port()](IterableNeighbourAttrs::get_port)\n- [.get_vni()](IterableNeighbourAttrs::get_vni)\n- [.get_ifindex()](IterableNeighbourAttrs::get_ifindex)\n- [.get_master()](IterableNeighbourAttrs::get_master)\n- [.get_protocol()](IterableNeighbourAttrs::get_protocol)\n- [.get_nh_id()](IterableNeighbourAttrs::get_nh_id)\n- [.get_fdb_ext_attrs()](IterableNeighbourAttrs::get_fdb_ext_attrs)\n- [.get_flags_ext()](IterableNeighbourAttrs::get_flags_ext)\n"]
3197    pub fn op_getneigh_do(self, header: &Ndmsg) -> OpGetneighDo<'buf> {
3198        let mut res = OpGetneighDo::new(self, header);
3199        res.request
3200            .do_writeback(res.protocol(), "op-getneigh-do", OpGetneighDo::lookup);
3201        res
3202    }
3203    #[doc = "Get or dump neighbour tables\n\nReply attributes:\n- [.get_name()](IterableNdtAttrs::get_name)\n- [.get_thresh1()](IterableNdtAttrs::get_thresh1)\n- [.get_thresh2()](IterableNdtAttrs::get_thresh2)\n- [.get_thresh3()](IterableNdtAttrs::get_thresh3)\n- [.get_config()](IterableNdtAttrs::get_config)\n- [.get_parms()](IterableNdtAttrs::get_parms)\n- [.get_stats()](IterableNdtAttrs::get_stats)\n- [.get_gc_interval()](IterableNdtAttrs::get_gc_interval)\n"]
3204    pub fn op_getneightbl_dump(self, header: &Ndtmsg) -> OpGetneightblDump<'buf> {
3205        let mut res = OpGetneightblDump::new(self, header);
3206        res.request.do_writeback(
3207            res.protocol(),
3208            "op-getneightbl-dump",
3209            OpGetneightblDump::lookup,
3210        );
3211        res
3212    }
3213    #[doc = "Set neighbour tables\nRequest attributes:\n- [.push_name()](PushNdtAttrs::push_name)\n- [.push_thresh1()](PushNdtAttrs::push_thresh1)\n- [.push_thresh2()](PushNdtAttrs::push_thresh2)\n- [.push_thresh3()](PushNdtAttrs::push_thresh3)\n- [.nested_parms()](PushNdtAttrs::nested_parms)\n- [.push_gc_interval()](PushNdtAttrs::push_gc_interval)\n"]
3214    pub fn op_setneightbl_do(self, header: &Ndtmsg) -> OpSetneightblDo<'buf> {
3215        let mut res = OpSetneightblDo::new(self, header);
3216        res.request
3217            .do_writeback(res.protocol(), "op-setneightbl-do", OpSetneightblDo::lookup);
3218        res
3219    }
3220}
3221#[cfg(test)]
3222mod generated_tests {
3223    use super::*;
3224    #[test]
3225    fn tests() {
3226        let _ = IterableNdtAttrs::get_config;
3227        let _ = IterableNdtAttrs::get_gc_interval;
3228        let _ = IterableNdtAttrs::get_name;
3229        let _ = IterableNdtAttrs::get_parms;
3230        let _ = IterableNdtAttrs::get_stats;
3231        let _ = IterableNdtAttrs::get_thresh1;
3232        let _ = IterableNdtAttrs::get_thresh2;
3233        let _ = IterableNdtAttrs::get_thresh3;
3234        let _ = IterableNeighbourAttrs::get_dst;
3235        let _ = IterableNeighbourAttrs::get_fdb_ext_attrs;
3236        let _ = IterableNeighbourAttrs::get_flags_ext;
3237        let _ = IterableNeighbourAttrs::get_ifindex;
3238        let _ = IterableNeighbourAttrs::get_lladdr;
3239        let _ = IterableNeighbourAttrs::get_master;
3240        let _ = IterableNeighbourAttrs::get_nh_id;
3241        let _ = IterableNeighbourAttrs::get_port;
3242        let _ = IterableNeighbourAttrs::get_probes;
3243        let _ = IterableNeighbourAttrs::get_protocol;
3244        let _ = IterableNeighbourAttrs::get_vlan;
3245        let _ = IterableNeighbourAttrs::get_vni;
3246        let _ = PushNdtAttrs::<&mut Vec<u8>>::nested_parms;
3247        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_gc_interval;
3248        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_name;
3249        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_thresh1;
3250        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_thresh2;
3251        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_thresh3;
3252        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_dst;
3253        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_fdb_ext_attrs;
3254        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_flags_ext;
3255        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_ifindex;
3256        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_lladdr;
3257        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_master;
3258        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_nh_id;
3259        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_port;
3260        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_probes;
3261        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_protocol;
3262        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_vlan;
3263        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_vni;
3264    }
3265}