Skip to main content

netlink_bindings/rt-neigh/
mod.rs

1#![doc = "IP neighbour management over rtnetlink.\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "rt-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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 mut pos;
872        let mut r#type;
873        loop {
874            pos = self.pos;
875            r#type = None;
876            if self.buf.len() == self.pos {
877                return None;
878            }
879            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
880                self.pos = self.buf.len();
881                break;
882            };
883            r#type = Some(header.r#type);
884            let res = match header.r#type {
885                0u16 => NeighbourAttrs::Unspec({
886                    let res = Some(next);
887                    let Some(val) = res else { break };
888                    val
889                }),
890                1u16 => NeighbourAttrs::Dst({
891                    let res = parse_ip(next);
892                    let Some(val) = res else { break };
893                    val
894                }),
895                2u16 => NeighbourAttrs::Lladdr({
896                    let res = Some(next);
897                    let Some(val) = res else { break };
898                    val
899                }),
900                3u16 => NeighbourAttrs::Cacheinfo({
901                    let res = Some(NdaCacheinfo::new_from_zeroed(next));
902                    let Some(val) = res else { break };
903                    val
904                }),
905                4u16 => NeighbourAttrs::Probes({
906                    let res = parse_u32(next);
907                    let Some(val) = res else { break };
908                    val
909                }),
910                5u16 => NeighbourAttrs::Vlan({
911                    let res = parse_u16(next);
912                    let Some(val) = res else { break };
913                    val
914                }),
915                6u16 => NeighbourAttrs::Port({
916                    let res = parse_u16(next);
917                    let Some(val) = res else { break };
918                    val
919                }),
920                7u16 => NeighbourAttrs::Vni({
921                    let res = parse_u32(next);
922                    let Some(val) = res else { break };
923                    val
924                }),
925                8u16 => NeighbourAttrs::Ifindex({
926                    let res = parse_u32(next);
927                    let Some(val) = res else { break };
928                    val
929                }),
930                9u16 => NeighbourAttrs::Master({
931                    let res = parse_u32(next);
932                    let Some(val) = res else { break };
933                    val
934                }),
935                10u16 => NeighbourAttrs::LinkNetnsid({
936                    let res = parse_i32(next);
937                    let Some(val) = res else { break };
938                    val
939                }),
940                11u16 => NeighbourAttrs::SrcVni({
941                    let res = parse_u32(next);
942                    let Some(val) = res else { break };
943                    val
944                }),
945                12u16 => NeighbourAttrs::Protocol({
946                    let res = parse_u8(next);
947                    let Some(val) = res else { break };
948                    val
949                }),
950                13u16 => NeighbourAttrs::NhId({
951                    let res = parse_u32(next);
952                    let Some(val) = res else { break };
953                    val
954                }),
955                14u16 => NeighbourAttrs::FdbExtAttrs({
956                    let res = Some(next);
957                    let Some(val) = res else { break };
958                    val
959                }),
960                15u16 => NeighbourAttrs::FlagsExt({
961                    let res = parse_u32(next);
962                    let Some(val) = res else { break };
963                    val
964                }),
965                16u16 => NeighbourAttrs::NdmStateMask({
966                    let res = parse_u16(next);
967                    let Some(val) = res else { break };
968                    val
969                }),
970                17u16 => NeighbourAttrs::NdmFlagsMask({
971                    let res = parse_u8(next);
972                    let Some(val) = res else { break };
973                    val
974                }),
975                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
976                n => continue,
977            };
978            return Some(Ok(res));
979        }
980        Some(Err(ErrorContext::new(
981            "NeighbourAttrs",
982            r#type.and_then(|t| NeighbourAttrs::attr_from_type(t)),
983            self.orig_loc,
984            self.buf.as_ptr().wrapping_add(pos) as usize,
985        )))
986    }
987}
988impl<'a> std::fmt::Debug for IterableNeighbourAttrs<'_> {
989    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
990        let mut fmt = f.debug_struct("NeighbourAttrs");
991        for attr in self.clone() {
992            let attr = match attr {
993                Ok(a) => a,
994                Err(err) => {
995                    fmt.finish()?;
996                    f.write_str("Err(")?;
997                    err.fmt(f)?;
998                    return f.write_str(")");
999                }
1000            };
1001            match attr {
1002                NeighbourAttrs::Unspec(val) => fmt.field("Unspec", &val),
1003                NeighbourAttrs::Dst(val) => fmt.field("Dst", &val),
1004                NeighbourAttrs::Lladdr(val) => fmt.field("Lladdr", &FormatMac(val)),
1005                NeighbourAttrs::Cacheinfo(val) => fmt.field("Cacheinfo", &val),
1006                NeighbourAttrs::Probes(val) => fmt.field("Probes", &val),
1007                NeighbourAttrs::Vlan(val) => fmt.field("Vlan", &val),
1008                NeighbourAttrs::Port(val) => fmt.field("Port", &val),
1009                NeighbourAttrs::Vni(val) => fmt.field("Vni", &val),
1010                NeighbourAttrs::Ifindex(val) => fmt.field("Ifindex", &val),
1011                NeighbourAttrs::Master(val) => fmt.field("Master", &val),
1012                NeighbourAttrs::LinkNetnsid(val) => fmt.field("LinkNetnsid", &val),
1013                NeighbourAttrs::SrcVni(val) => fmt.field("SrcVni", &val),
1014                NeighbourAttrs::Protocol(val) => fmt.field("Protocol", &val),
1015                NeighbourAttrs::NhId(val) => fmt.field("NhId", &val),
1016                NeighbourAttrs::FdbExtAttrs(val) => fmt.field("FdbExtAttrs", &val),
1017                NeighbourAttrs::FlagsExt(val) => fmt.field(
1018                    "FlagsExt",
1019                    &FormatFlags(val.into(), NtfExtFlags::from_value),
1020                ),
1021                NeighbourAttrs::NdmStateMask(val) => fmt.field("NdmStateMask", &val),
1022                NeighbourAttrs::NdmFlagsMask(val) => fmt.field("NdmFlagsMask", &val),
1023            };
1024        }
1025        fmt.finish()
1026    }
1027}
1028impl IterableNeighbourAttrs<'_> {
1029    pub fn lookup_attr(
1030        &self,
1031        offset: usize,
1032        missing_type: Option<u16>,
1033    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1034        let mut stack = Vec::new();
1035        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1036        if missing_type.is_some() && cur == offset {
1037            stack.push(("NeighbourAttrs", offset));
1038            return (
1039                stack,
1040                missing_type.and_then(|t| NeighbourAttrs::attr_from_type(t)),
1041            );
1042        }
1043        if cur > offset || cur + self.buf.len() < offset {
1044            return (stack, None);
1045        }
1046        let mut attrs = self.clone();
1047        let mut last_off = cur + attrs.pos;
1048        while let Some(attr) = attrs.next() {
1049            let Ok(attr) = attr else { break };
1050            match attr {
1051                NeighbourAttrs::Unspec(val) => {
1052                    if last_off == offset {
1053                        stack.push(("Unspec", last_off));
1054                        break;
1055                    }
1056                }
1057                NeighbourAttrs::Dst(val) => {
1058                    if last_off == offset {
1059                        stack.push(("Dst", last_off));
1060                        break;
1061                    }
1062                }
1063                NeighbourAttrs::Lladdr(val) => {
1064                    if last_off == offset {
1065                        stack.push(("Lladdr", last_off));
1066                        break;
1067                    }
1068                }
1069                NeighbourAttrs::Cacheinfo(val) => {
1070                    if last_off == offset {
1071                        stack.push(("Cacheinfo", last_off));
1072                        break;
1073                    }
1074                }
1075                NeighbourAttrs::Probes(val) => {
1076                    if last_off == offset {
1077                        stack.push(("Probes", last_off));
1078                        break;
1079                    }
1080                }
1081                NeighbourAttrs::Vlan(val) => {
1082                    if last_off == offset {
1083                        stack.push(("Vlan", last_off));
1084                        break;
1085                    }
1086                }
1087                NeighbourAttrs::Port(val) => {
1088                    if last_off == offset {
1089                        stack.push(("Port", last_off));
1090                        break;
1091                    }
1092                }
1093                NeighbourAttrs::Vni(val) => {
1094                    if last_off == offset {
1095                        stack.push(("Vni", last_off));
1096                        break;
1097                    }
1098                }
1099                NeighbourAttrs::Ifindex(val) => {
1100                    if last_off == offset {
1101                        stack.push(("Ifindex", last_off));
1102                        break;
1103                    }
1104                }
1105                NeighbourAttrs::Master(val) => {
1106                    if last_off == offset {
1107                        stack.push(("Master", last_off));
1108                        break;
1109                    }
1110                }
1111                NeighbourAttrs::LinkNetnsid(val) => {
1112                    if last_off == offset {
1113                        stack.push(("LinkNetnsid", last_off));
1114                        break;
1115                    }
1116                }
1117                NeighbourAttrs::SrcVni(val) => {
1118                    if last_off == offset {
1119                        stack.push(("SrcVni", last_off));
1120                        break;
1121                    }
1122                }
1123                NeighbourAttrs::Protocol(val) => {
1124                    if last_off == offset {
1125                        stack.push(("Protocol", last_off));
1126                        break;
1127                    }
1128                }
1129                NeighbourAttrs::NhId(val) => {
1130                    if last_off == offset {
1131                        stack.push(("NhId", last_off));
1132                        break;
1133                    }
1134                }
1135                NeighbourAttrs::FdbExtAttrs(val) => {
1136                    if last_off == offset {
1137                        stack.push(("FdbExtAttrs", last_off));
1138                        break;
1139                    }
1140                }
1141                NeighbourAttrs::FlagsExt(val) => {
1142                    if last_off == offset {
1143                        stack.push(("FlagsExt", last_off));
1144                        break;
1145                    }
1146                }
1147                NeighbourAttrs::NdmStateMask(val) => {
1148                    if last_off == offset {
1149                        stack.push(("NdmStateMask", last_off));
1150                        break;
1151                    }
1152                }
1153                NeighbourAttrs::NdmFlagsMask(val) => {
1154                    if last_off == offset {
1155                        stack.push(("NdmFlagsMask", last_off));
1156                        break;
1157                    }
1158                }
1159                _ => {}
1160            };
1161            last_off = cur + attrs.pos;
1162        }
1163        if !stack.is_empty() {
1164            stack.push(("NeighbourAttrs", cur));
1165        }
1166        (stack, None)
1167    }
1168}
1169#[derive(Clone)]
1170pub enum NdtAttrs<'a> {
1171    Name(&'a CStr),
1172    Thresh1(u32),
1173    Thresh2(u32),
1174    Thresh3(u32),
1175    Config(NdtConfig),
1176    Parms(IterableNdtpaAttrs<'a>),
1177    Stats(NdtStats),
1178    GcInterval(u64),
1179    Pad(&'a [u8]),
1180}
1181impl<'a> IterableNdtAttrs<'a> {
1182    pub fn get_name(&self) -> Result<&'a CStr, ErrorContext> {
1183        let mut iter = self.clone();
1184        iter.pos = 0;
1185        for attr in iter {
1186            if let Ok(NdtAttrs::Name(val)) = attr {
1187                return Ok(val);
1188            }
1189        }
1190        Err(ErrorContext::new_missing(
1191            "NdtAttrs",
1192            "Name",
1193            self.orig_loc,
1194            self.buf.as_ptr() as usize,
1195        ))
1196    }
1197    pub fn get_thresh1(&self) -> Result<u32, ErrorContext> {
1198        let mut iter = self.clone();
1199        iter.pos = 0;
1200        for attr in iter {
1201            if let Ok(NdtAttrs::Thresh1(val)) = attr {
1202                return Ok(val);
1203            }
1204        }
1205        Err(ErrorContext::new_missing(
1206            "NdtAttrs",
1207            "Thresh1",
1208            self.orig_loc,
1209            self.buf.as_ptr() as usize,
1210        ))
1211    }
1212    pub fn get_thresh2(&self) -> Result<u32, ErrorContext> {
1213        let mut iter = self.clone();
1214        iter.pos = 0;
1215        for attr in iter {
1216            if let Ok(NdtAttrs::Thresh2(val)) = attr {
1217                return Ok(val);
1218            }
1219        }
1220        Err(ErrorContext::new_missing(
1221            "NdtAttrs",
1222            "Thresh2",
1223            self.orig_loc,
1224            self.buf.as_ptr() as usize,
1225        ))
1226    }
1227    pub fn get_thresh3(&self) -> Result<u32, ErrorContext> {
1228        let mut iter = self.clone();
1229        iter.pos = 0;
1230        for attr in iter {
1231            if let Ok(NdtAttrs::Thresh3(val)) = attr {
1232                return Ok(val);
1233            }
1234        }
1235        Err(ErrorContext::new_missing(
1236            "NdtAttrs",
1237            "Thresh3",
1238            self.orig_loc,
1239            self.buf.as_ptr() as usize,
1240        ))
1241    }
1242    pub fn get_config(&self) -> Result<NdtConfig, ErrorContext> {
1243        let mut iter = self.clone();
1244        iter.pos = 0;
1245        for attr in iter {
1246            if let Ok(NdtAttrs::Config(val)) = attr {
1247                return Ok(val);
1248            }
1249        }
1250        Err(ErrorContext::new_missing(
1251            "NdtAttrs",
1252            "Config",
1253            self.orig_loc,
1254            self.buf.as_ptr() as usize,
1255        ))
1256    }
1257    pub fn get_parms(&self) -> Result<IterableNdtpaAttrs<'a>, ErrorContext> {
1258        let mut iter = self.clone();
1259        iter.pos = 0;
1260        for attr in iter {
1261            if let Ok(NdtAttrs::Parms(val)) = attr {
1262                return Ok(val);
1263            }
1264        }
1265        Err(ErrorContext::new_missing(
1266            "NdtAttrs",
1267            "Parms",
1268            self.orig_loc,
1269            self.buf.as_ptr() as usize,
1270        ))
1271    }
1272    pub fn get_stats(&self) -> Result<NdtStats, ErrorContext> {
1273        let mut iter = self.clone();
1274        iter.pos = 0;
1275        for attr in iter {
1276            if let Ok(NdtAttrs::Stats(val)) = attr {
1277                return Ok(val);
1278            }
1279        }
1280        Err(ErrorContext::new_missing(
1281            "NdtAttrs",
1282            "Stats",
1283            self.orig_loc,
1284            self.buf.as_ptr() as usize,
1285        ))
1286    }
1287    pub fn get_gc_interval(&self) -> Result<u64, ErrorContext> {
1288        let mut iter = self.clone();
1289        iter.pos = 0;
1290        for attr in iter {
1291            if let Ok(NdtAttrs::GcInterval(val)) = attr {
1292                return Ok(val);
1293            }
1294        }
1295        Err(ErrorContext::new_missing(
1296            "NdtAttrs",
1297            "GcInterval",
1298            self.orig_loc,
1299            self.buf.as_ptr() as usize,
1300        ))
1301    }
1302    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
1303        let mut iter = self.clone();
1304        iter.pos = 0;
1305        for attr in iter {
1306            if let Ok(NdtAttrs::Pad(val)) = attr {
1307                return Ok(val);
1308            }
1309        }
1310        Err(ErrorContext::new_missing(
1311            "NdtAttrs",
1312            "Pad",
1313            self.orig_loc,
1314            self.buf.as_ptr() as usize,
1315        ))
1316    }
1317}
1318impl NdtAttrs<'_> {
1319    pub fn new<'a>(buf: &'a [u8]) -> IterableNdtAttrs<'a> {
1320        IterableNdtAttrs::with_loc(buf, buf.as_ptr() as usize)
1321    }
1322    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1323        let res = match r#type {
1324            1u16 => "Name",
1325            2u16 => "Thresh1",
1326            3u16 => "Thresh2",
1327            4u16 => "Thresh3",
1328            5u16 => "Config",
1329            6u16 => "Parms",
1330            7u16 => "Stats",
1331            8u16 => "GcInterval",
1332            9u16 => "Pad",
1333            _ => return None,
1334        };
1335        Some(res)
1336    }
1337}
1338#[derive(Clone, Copy, Default)]
1339pub struct IterableNdtAttrs<'a> {
1340    buf: &'a [u8],
1341    pos: usize,
1342    orig_loc: usize,
1343}
1344impl<'a> IterableNdtAttrs<'a> {
1345    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1346        Self {
1347            buf,
1348            pos: 0,
1349            orig_loc,
1350        }
1351    }
1352    pub fn get_buf(&self) -> &'a [u8] {
1353        self.buf
1354    }
1355}
1356impl<'a> Iterator for IterableNdtAttrs<'a> {
1357    type Item = Result<NdtAttrs<'a>, ErrorContext>;
1358    fn next(&mut self) -> Option<Self::Item> {
1359        let mut pos;
1360        let mut r#type;
1361        loop {
1362            pos = self.pos;
1363            r#type = None;
1364            if self.buf.len() == self.pos {
1365                return None;
1366            }
1367            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1368                self.pos = self.buf.len();
1369                break;
1370            };
1371            r#type = Some(header.r#type);
1372            let res = match header.r#type {
1373                1u16 => NdtAttrs::Name({
1374                    let res = CStr::from_bytes_with_nul(next).ok();
1375                    let Some(val) = res else { break };
1376                    val
1377                }),
1378                2u16 => NdtAttrs::Thresh1({
1379                    let res = parse_u32(next);
1380                    let Some(val) = res else { break };
1381                    val
1382                }),
1383                3u16 => NdtAttrs::Thresh2({
1384                    let res = parse_u32(next);
1385                    let Some(val) = res else { break };
1386                    val
1387                }),
1388                4u16 => NdtAttrs::Thresh3({
1389                    let res = parse_u32(next);
1390                    let Some(val) = res else { break };
1391                    val
1392                }),
1393                5u16 => NdtAttrs::Config({
1394                    let res = Some(NdtConfig::new_from_zeroed(next));
1395                    let Some(val) = res else { break };
1396                    val
1397                }),
1398                6u16 => NdtAttrs::Parms({
1399                    let res = Some(IterableNdtpaAttrs::with_loc(next, self.orig_loc));
1400                    let Some(val) = res else { break };
1401                    val
1402                }),
1403                7u16 => NdtAttrs::Stats({
1404                    let res = Some(NdtStats::new_from_zeroed(next));
1405                    let Some(val) = res else { break };
1406                    val
1407                }),
1408                8u16 => NdtAttrs::GcInterval({
1409                    let res = parse_u64(next);
1410                    let Some(val) = res else { break };
1411                    val
1412                }),
1413                9u16 => NdtAttrs::Pad({
1414                    let res = Some(next);
1415                    let Some(val) = res else { break };
1416                    val
1417                }),
1418                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1419                n => continue,
1420            };
1421            return Some(Ok(res));
1422        }
1423        Some(Err(ErrorContext::new(
1424            "NdtAttrs",
1425            r#type.and_then(|t| NdtAttrs::attr_from_type(t)),
1426            self.orig_loc,
1427            self.buf.as_ptr().wrapping_add(pos) as usize,
1428        )))
1429    }
1430}
1431impl<'a> std::fmt::Debug for IterableNdtAttrs<'_> {
1432    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1433        let mut fmt = f.debug_struct("NdtAttrs");
1434        for attr in self.clone() {
1435            let attr = match attr {
1436                Ok(a) => a,
1437                Err(err) => {
1438                    fmt.finish()?;
1439                    f.write_str("Err(")?;
1440                    err.fmt(f)?;
1441                    return f.write_str(")");
1442                }
1443            };
1444            match attr {
1445                NdtAttrs::Name(val) => fmt.field("Name", &val),
1446                NdtAttrs::Thresh1(val) => fmt.field("Thresh1", &val),
1447                NdtAttrs::Thresh2(val) => fmt.field("Thresh2", &val),
1448                NdtAttrs::Thresh3(val) => fmt.field("Thresh3", &val),
1449                NdtAttrs::Config(val) => fmt.field("Config", &val),
1450                NdtAttrs::Parms(val) => fmt.field("Parms", &val),
1451                NdtAttrs::Stats(val) => fmt.field("Stats", &val),
1452                NdtAttrs::GcInterval(val) => fmt.field("GcInterval", &val),
1453                NdtAttrs::Pad(val) => fmt.field("Pad", &val),
1454            };
1455        }
1456        fmt.finish()
1457    }
1458}
1459impl IterableNdtAttrs<'_> {
1460    pub fn lookup_attr(
1461        &self,
1462        offset: usize,
1463        missing_type: Option<u16>,
1464    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1465        let mut stack = Vec::new();
1466        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1467        if missing_type.is_some() && cur == offset {
1468            stack.push(("NdtAttrs", offset));
1469            return (
1470                stack,
1471                missing_type.and_then(|t| NdtAttrs::attr_from_type(t)),
1472            );
1473        }
1474        if cur > offset || cur + self.buf.len() < offset {
1475            return (stack, None);
1476        }
1477        let mut attrs = self.clone();
1478        let mut last_off = cur + attrs.pos;
1479        let mut missing = None;
1480        while let Some(attr) = attrs.next() {
1481            let Ok(attr) = attr else { break };
1482            match attr {
1483                NdtAttrs::Name(val) => {
1484                    if last_off == offset {
1485                        stack.push(("Name", last_off));
1486                        break;
1487                    }
1488                }
1489                NdtAttrs::Thresh1(val) => {
1490                    if last_off == offset {
1491                        stack.push(("Thresh1", last_off));
1492                        break;
1493                    }
1494                }
1495                NdtAttrs::Thresh2(val) => {
1496                    if last_off == offset {
1497                        stack.push(("Thresh2", last_off));
1498                        break;
1499                    }
1500                }
1501                NdtAttrs::Thresh3(val) => {
1502                    if last_off == offset {
1503                        stack.push(("Thresh3", last_off));
1504                        break;
1505                    }
1506                }
1507                NdtAttrs::Config(val) => {
1508                    if last_off == offset {
1509                        stack.push(("Config", last_off));
1510                        break;
1511                    }
1512                }
1513                NdtAttrs::Parms(val) => {
1514                    (stack, missing) = val.lookup_attr(offset, missing_type);
1515                    if !stack.is_empty() {
1516                        break;
1517                    }
1518                }
1519                NdtAttrs::Stats(val) => {
1520                    if last_off == offset {
1521                        stack.push(("Stats", last_off));
1522                        break;
1523                    }
1524                }
1525                NdtAttrs::GcInterval(val) => {
1526                    if last_off == offset {
1527                        stack.push(("GcInterval", last_off));
1528                        break;
1529                    }
1530                }
1531                NdtAttrs::Pad(val) => {
1532                    if last_off == offset {
1533                        stack.push(("Pad", last_off));
1534                        break;
1535                    }
1536                }
1537                _ => {}
1538            };
1539            last_off = cur + attrs.pos;
1540        }
1541        if !stack.is_empty() {
1542            stack.push(("NdtAttrs", cur));
1543        }
1544        (stack, missing)
1545    }
1546}
1547#[derive(Clone)]
1548pub enum NdtpaAttrs<'a> {
1549    Ifindex(u32),
1550    Refcnt(u32),
1551    ReachableTime(u64),
1552    BaseReachableTime(u64),
1553    RetransTime(u64),
1554    GcStaletime(u64),
1555    DelayProbeTime(u64),
1556    QueueLen(u32),
1557    AppProbes(u32),
1558    UcastProbes(u32),
1559    McastProbes(u32),
1560    AnycastDelay(u64),
1561    ProxyDelay(u64),
1562    ProxyQlen(u32),
1563    Locktime(u64),
1564    QueueLenbytes(u32),
1565    McastReprobes(u32),
1566    Pad(&'a [u8]),
1567    IntervalProbeTimeMs(u64),
1568}
1569impl<'a> IterableNdtpaAttrs<'a> {
1570    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
1571        let mut iter = self.clone();
1572        iter.pos = 0;
1573        for attr in iter {
1574            if let Ok(NdtpaAttrs::Ifindex(val)) = attr {
1575                return Ok(val);
1576            }
1577        }
1578        Err(ErrorContext::new_missing(
1579            "NdtpaAttrs",
1580            "Ifindex",
1581            self.orig_loc,
1582            self.buf.as_ptr() as usize,
1583        ))
1584    }
1585    pub fn get_refcnt(&self) -> Result<u32, ErrorContext> {
1586        let mut iter = self.clone();
1587        iter.pos = 0;
1588        for attr in iter {
1589            if let Ok(NdtpaAttrs::Refcnt(val)) = attr {
1590                return Ok(val);
1591            }
1592        }
1593        Err(ErrorContext::new_missing(
1594            "NdtpaAttrs",
1595            "Refcnt",
1596            self.orig_loc,
1597            self.buf.as_ptr() as usize,
1598        ))
1599    }
1600    pub fn get_reachable_time(&self) -> Result<u64, ErrorContext> {
1601        let mut iter = self.clone();
1602        iter.pos = 0;
1603        for attr in iter {
1604            if let Ok(NdtpaAttrs::ReachableTime(val)) = attr {
1605                return Ok(val);
1606            }
1607        }
1608        Err(ErrorContext::new_missing(
1609            "NdtpaAttrs",
1610            "ReachableTime",
1611            self.orig_loc,
1612            self.buf.as_ptr() as usize,
1613        ))
1614    }
1615    pub fn get_base_reachable_time(&self) -> Result<u64, ErrorContext> {
1616        let mut iter = self.clone();
1617        iter.pos = 0;
1618        for attr in iter {
1619            if let Ok(NdtpaAttrs::BaseReachableTime(val)) = attr {
1620                return Ok(val);
1621            }
1622        }
1623        Err(ErrorContext::new_missing(
1624            "NdtpaAttrs",
1625            "BaseReachableTime",
1626            self.orig_loc,
1627            self.buf.as_ptr() as usize,
1628        ))
1629    }
1630    pub fn get_retrans_time(&self) -> Result<u64, ErrorContext> {
1631        let mut iter = self.clone();
1632        iter.pos = 0;
1633        for attr in iter {
1634            if let Ok(NdtpaAttrs::RetransTime(val)) = attr {
1635                return Ok(val);
1636            }
1637        }
1638        Err(ErrorContext::new_missing(
1639            "NdtpaAttrs",
1640            "RetransTime",
1641            self.orig_loc,
1642            self.buf.as_ptr() as usize,
1643        ))
1644    }
1645    pub fn get_gc_staletime(&self) -> Result<u64, ErrorContext> {
1646        let mut iter = self.clone();
1647        iter.pos = 0;
1648        for attr in iter {
1649            if let Ok(NdtpaAttrs::GcStaletime(val)) = attr {
1650                return Ok(val);
1651            }
1652        }
1653        Err(ErrorContext::new_missing(
1654            "NdtpaAttrs",
1655            "GcStaletime",
1656            self.orig_loc,
1657            self.buf.as_ptr() as usize,
1658        ))
1659    }
1660    pub fn get_delay_probe_time(&self) -> Result<u64, ErrorContext> {
1661        let mut iter = self.clone();
1662        iter.pos = 0;
1663        for attr in iter {
1664            if let Ok(NdtpaAttrs::DelayProbeTime(val)) = attr {
1665                return Ok(val);
1666            }
1667        }
1668        Err(ErrorContext::new_missing(
1669            "NdtpaAttrs",
1670            "DelayProbeTime",
1671            self.orig_loc,
1672            self.buf.as_ptr() as usize,
1673        ))
1674    }
1675    pub fn get_queue_len(&self) -> Result<u32, ErrorContext> {
1676        let mut iter = self.clone();
1677        iter.pos = 0;
1678        for attr in iter {
1679            if let Ok(NdtpaAttrs::QueueLen(val)) = attr {
1680                return Ok(val);
1681            }
1682        }
1683        Err(ErrorContext::new_missing(
1684            "NdtpaAttrs",
1685            "QueueLen",
1686            self.orig_loc,
1687            self.buf.as_ptr() as usize,
1688        ))
1689    }
1690    pub fn get_app_probes(&self) -> Result<u32, ErrorContext> {
1691        let mut iter = self.clone();
1692        iter.pos = 0;
1693        for attr in iter {
1694            if let Ok(NdtpaAttrs::AppProbes(val)) = attr {
1695                return Ok(val);
1696            }
1697        }
1698        Err(ErrorContext::new_missing(
1699            "NdtpaAttrs",
1700            "AppProbes",
1701            self.orig_loc,
1702            self.buf.as_ptr() as usize,
1703        ))
1704    }
1705    pub fn get_ucast_probes(&self) -> Result<u32, ErrorContext> {
1706        let mut iter = self.clone();
1707        iter.pos = 0;
1708        for attr in iter {
1709            if let Ok(NdtpaAttrs::UcastProbes(val)) = attr {
1710                return Ok(val);
1711            }
1712        }
1713        Err(ErrorContext::new_missing(
1714            "NdtpaAttrs",
1715            "UcastProbes",
1716            self.orig_loc,
1717            self.buf.as_ptr() as usize,
1718        ))
1719    }
1720    pub fn get_mcast_probes(&self) -> Result<u32, ErrorContext> {
1721        let mut iter = self.clone();
1722        iter.pos = 0;
1723        for attr in iter {
1724            if let Ok(NdtpaAttrs::McastProbes(val)) = attr {
1725                return Ok(val);
1726            }
1727        }
1728        Err(ErrorContext::new_missing(
1729            "NdtpaAttrs",
1730            "McastProbes",
1731            self.orig_loc,
1732            self.buf.as_ptr() as usize,
1733        ))
1734    }
1735    pub fn get_anycast_delay(&self) -> Result<u64, ErrorContext> {
1736        let mut iter = self.clone();
1737        iter.pos = 0;
1738        for attr in iter {
1739            if let Ok(NdtpaAttrs::AnycastDelay(val)) = attr {
1740                return Ok(val);
1741            }
1742        }
1743        Err(ErrorContext::new_missing(
1744            "NdtpaAttrs",
1745            "AnycastDelay",
1746            self.orig_loc,
1747            self.buf.as_ptr() as usize,
1748        ))
1749    }
1750    pub fn get_proxy_delay(&self) -> Result<u64, ErrorContext> {
1751        let mut iter = self.clone();
1752        iter.pos = 0;
1753        for attr in iter {
1754            if let Ok(NdtpaAttrs::ProxyDelay(val)) = attr {
1755                return Ok(val);
1756            }
1757        }
1758        Err(ErrorContext::new_missing(
1759            "NdtpaAttrs",
1760            "ProxyDelay",
1761            self.orig_loc,
1762            self.buf.as_ptr() as usize,
1763        ))
1764    }
1765    pub fn get_proxy_qlen(&self) -> Result<u32, ErrorContext> {
1766        let mut iter = self.clone();
1767        iter.pos = 0;
1768        for attr in iter {
1769            if let Ok(NdtpaAttrs::ProxyQlen(val)) = attr {
1770                return Ok(val);
1771            }
1772        }
1773        Err(ErrorContext::new_missing(
1774            "NdtpaAttrs",
1775            "ProxyQlen",
1776            self.orig_loc,
1777            self.buf.as_ptr() as usize,
1778        ))
1779    }
1780    pub fn get_locktime(&self) -> Result<u64, ErrorContext> {
1781        let mut iter = self.clone();
1782        iter.pos = 0;
1783        for attr in iter {
1784            if let Ok(NdtpaAttrs::Locktime(val)) = attr {
1785                return Ok(val);
1786            }
1787        }
1788        Err(ErrorContext::new_missing(
1789            "NdtpaAttrs",
1790            "Locktime",
1791            self.orig_loc,
1792            self.buf.as_ptr() as usize,
1793        ))
1794    }
1795    pub fn get_queue_lenbytes(&self) -> Result<u32, ErrorContext> {
1796        let mut iter = self.clone();
1797        iter.pos = 0;
1798        for attr in iter {
1799            if let Ok(NdtpaAttrs::QueueLenbytes(val)) = attr {
1800                return Ok(val);
1801            }
1802        }
1803        Err(ErrorContext::new_missing(
1804            "NdtpaAttrs",
1805            "QueueLenbytes",
1806            self.orig_loc,
1807            self.buf.as_ptr() as usize,
1808        ))
1809    }
1810    pub fn get_mcast_reprobes(&self) -> Result<u32, ErrorContext> {
1811        let mut iter = self.clone();
1812        iter.pos = 0;
1813        for attr in iter {
1814            if let Ok(NdtpaAttrs::McastReprobes(val)) = attr {
1815                return Ok(val);
1816            }
1817        }
1818        Err(ErrorContext::new_missing(
1819            "NdtpaAttrs",
1820            "McastReprobes",
1821            self.orig_loc,
1822            self.buf.as_ptr() as usize,
1823        ))
1824    }
1825    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
1826        let mut iter = self.clone();
1827        iter.pos = 0;
1828        for attr in iter {
1829            if let Ok(NdtpaAttrs::Pad(val)) = attr {
1830                return Ok(val);
1831            }
1832        }
1833        Err(ErrorContext::new_missing(
1834            "NdtpaAttrs",
1835            "Pad",
1836            self.orig_loc,
1837            self.buf.as_ptr() as usize,
1838        ))
1839    }
1840    pub fn get_interval_probe_time_ms(&self) -> Result<u64, ErrorContext> {
1841        let mut iter = self.clone();
1842        iter.pos = 0;
1843        for attr in iter {
1844            if let Ok(NdtpaAttrs::IntervalProbeTimeMs(val)) = attr {
1845                return Ok(val);
1846            }
1847        }
1848        Err(ErrorContext::new_missing(
1849            "NdtpaAttrs",
1850            "IntervalProbeTimeMs",
1851            self.orig_loc,
1852            self.buf.as_ptr() as usize,
1853        ))
1854    }
1855}
1856impl NdtpaAttrs<'_> {
1857    pub fn new<'a>(buf: &'a [u8]) -> IterableNdtpaAttrs<'a> {
1858        IterableNdtpaAttrs::with_loc(buf, buf.as_ptr() as usize)
1859    }
1860    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1861        let res = match r#type {
1862            1u16 => "Ifindex",
1863            2u16 => "Refcnt",
1864            3u16 => "ReachableTime",
1865            4u16 => "BaseReachableTime",
1866            5u16 => "RetransTime",
1867            6u16 => "GcStaletime",
1868            7u16 => "DelayProbeTime",
1869            8u16 => "QueueLen",
1870            9u16 => "AppProbes",
1871            10u16 => "UcastProbes",
1872            11u16 => "McastProbes",
1873            12u16 => "AnycastDelay",
1874            13u16 => "ProxyDelay",
1875            14u16 => "ProxyQlen",
1876            15u16 => "Locktime",
1877            16u16 => "QueueLenbytes",
1878            17u16 => "McastReprobes",
1879            18u16 => "Pad",
1880            19u16 => "IntervalProbeTimeMs",
1881            _ => return None,
1882        };
1883        Some(res)
1884    }
1885}
1886#[derive(Clone, Copy, Default)]
1887pub struct IterableNdtpaAttrs<'a> {
1888    buf: &'a [u8],
1889    pos: usize,
1890    orig_loc: usize,
1891}
1892impl<'a> IterableNdtpaAttrs<'a> {
1893    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1894        Self {
1895            buf,
1896            pos: 0,
1897            orig_loc,
1898        }
1899    }
1900    pub fn get_buf(&self) -> &'a [u8] {
1901        self.buf
1902    }
1903}
1904impl<'a> Iterator for IterableNdtpaAttrs<'a> {
1905    type Item = Result<NdtpaAttrs<'a>, ErrorContext>;
1906    fn next(&mut self) -> Option<Self::Item> {
1907        let mut pos;
1908        let mut r#type;
1909        loop {
1910            pos = self.pos;
1911            r#type = None;
1912            if self.buf.len() == self.pos {
1913                return None;
1914            }
1915            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1916                self.pos = self.buf.len();
1917                break;
1918            };
1919            r#type = Some(header.r#type);
1920            let res = match header.r#type {
1921                1u16 => NdtpaAttrs::Ifindex({
1922                    let res = parse_u32(next);
1923                    let Some(val) = res else { break };
1924                    val
1925                }),
1926                2u16 => NdtpaAttrs::Refcnt({
1927                    let res = parse_u32(next);
1928                    let Some(val) = res else { break };
1929                    val
1930                }),
1931                3u16 => NdtpaAttrs::ReachableTime({
1932                    let res = parse_u64(next);
1933                    let Some(val) = res else { break };
1934                    val
1935                }),
1936                4u16 => NdtpaAttrs::BaseReachableTime({
1937                    let res = parse_u64(next);
1938                    let Some(val) = res else { break };
1939                    val
1940                }),
1941                5u16 => NdtpaAttrs::RetransTime({
1942                    let res = parse_u64(next);
1943                    let Some(val) = res else { break };
1944                    val
1945                }),
1946                6u16 => NdtpaAttrs::GcStaletime({
1947                    let res = parse_u64(next);
1948                    let Some(val) = res else { break };
1949                    val
1950                }),
1951                7u16 => NdtpaAttrs::DelayProbeTime({
1952                    let res = parse_u64(next);
1953                    let Some(val) = res else { break };
1954                    val
1955                }),
1956                8u16 => NdtpaAttrs::QueueLen({
1957                    let res = parse_u32(next);
1958                    let Some(val) = res else { break };
1959                    val
1960                }),
1961                9u16 => NdtpaAttrs::AppProbes({
1962                    let res = parse_u32(next);
1963                    let Some(val) = res else { break };
1964                    val
1965                }),
1966                10u16 => NdtpaAttrs::UcastProbes({
1967                    let res = parse_u32(next);
1968                    let Some(val) = res else { break };
1969                    val
1970                }),
1971                11u16 => NdtpaAttrs::McastProbes({
1972                    let res = parse_u32(next);
1973                    let Some(val) = res else { break };
1974                    val
1975                }),
1976                12u16 => NdtpaAttrs::AnycastDelay({
1977                    let res = parse_u64(next);
1978                    let Some(val) = res else { break };
1979                    val
1980                }),
1981                13u16 => NdtpaAttrs::ProxyDelay({
1982                    let res = parse_u64(next);
1983                    let Some(val) = res else { break };
1984                    val
1985                }),
1986                14u16 => NdtpaAttrs::ProxyQlen({
1987                    let res = parse_u32(next);
1988                    let Some(val) = res else { break };
1989                    val
1990                }),
1991                15u16 => NdtpaAttrs::Locktime({
1992                    let res = parse_u64(next);
1993                    let Some(val) = res else { break };
1994                    val
1995                }),
1996                16u16 => NdtpaAttrs::QueueLenbytes({
1997                    let res = parse_u32(next);
1998                    let Some(val) = res else { break };
1999                    val
2000                }),
2001                17u16 => NdtpaAttrs::McastReprobes({
2002                    let res = parse_u32(next);
2003                    let Some(val) = res else { break };
2004                    val
2005                }),
2006                18u16 => NdtpaAttrs::Pad({
2007                    let res = Some(next);
2008                    let Some(val) = res else { break };
2009                    val
2010                }),
2011                19u16 => NdtpaAttrs::IntervalProbeTimeMs({
2012                    let res = parse_u64(next);
2013                    let Some(val) = res else { break };
2014                    val
2015                }),
2016                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2017                n => continue,
2018            };
2019            return Some(Ok(res));
2020        }
2021        Some(Err(ErrorContext::new(
2022            "NdtpaAttrs",
2023            r#type.and_then(|t| NdtpaAttrs::attr_from_type(t)),
2024            self.orig_loc,
2025            self.buf.as_ptr().wrapping_add(pos) as usize,
2026        )))
2027    }
2028}
2029impl<'a> std::fmt::Debug for IterableNdtpaAttrs<'_> {
2030    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2031        let mut fmt = f.debug_struct("NdtpaAttrs");
2032        for attr in self.clone() {
2033            let attr = match attr {
2034                Ok(a) => a,
2035                Err(err) => {
2036                    fmt.finish()?;
2037                    f.write_str("Err(")?;
2038                    err.fmt(f)?;
2039                    return f.write_str(")");
2040                }
2041            };
2042            match attr {
2043                NdtpaAttrs::Ifindex(val) => fmt.field("Ifindex", &val),
2044                NdtpaAttrs::Refcnt(val) => fmt.field("Refcnt", &val),
2045                NdtpaAttrs::ReachableTime(val) => fmt.field("ReachableTime", &val),
2046                NdtpaAttrs::BaseReachableTime(val) => fmt.field("BaseReachableTime", &val),
2047                NdtpaAttrs::RetransTime(val) => fmt.field("RetransTime", &val),
2048                NdtpaAttrs::GcStaletime(val) => fmt.field("GcStaletime", &val),
2049                NdtpaAttrs::DelayProbeTime(val) => fmt.field("DelayProbeTime", &val),
2050                NdtpaAttrs::QueueLen(val) => fmt.field("QueueLen", &val),
2051                NdtpaAttrs::AppProbes(val) => fmt.field("AppProbes", &val),
2052                NdtpaAttrs::UcastProbes(val) => fmt.field("UcastProbes", &val),
2053                NdtpaAttrs::McastProbes(val) => fmt.field("McastProbes", &val),
2054                NdtpaAttrs::AnycastDelay(val) => fmt.field("AnycastDelay", &val),
2055                NdtpaAttrs::ProxyDelay(val) => fmt.field("ProxyDelay", &val),
2056                NdtpaAttrs::ProxyQlen(val) => fmt.field("ProxyQlen", &val),
2057                NdtpaAttrs::Locktime(val) => fmt.field("Locktime", &val),
2058                NdtpaAttrs::QueueLenbytes(val) => fmt.field("QueueLenbytes", &val),
2059                NdtpaAttrs::McastReprobes(val) => fmt.field("McastReprobes", &val),
2060                NdtpaAttrs::Pad(val) => fmt.field("Pad", &val),
2061                NdtpaAttrs::IntervalProbeTimeMs(val) => fmt.field("IntervalProbeTimeMs", &val),
2062            };
2063        }
2064        fmt.finish()
2065    }
2066}
2067impl IterableNdtpaAttrs<'_> {
2068    pub fn lookup_attr(
2069        &self,
2070        offset: usize,
2071        missing_type: Option<u16>,
2072    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2073        let mut stack = Vec::new();
2074        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2075        if missing_type.is_some() && cur == offset {
2076            stack.push(("NdtpaAttrs", offset));
2077            return (
2078                stack,
2079                missing_type.and_then(|t| NdtpaAttrs::attr_from_type(t)),
2080            );
2081        }
2082        if cur > offset || cur + self.buf.len() < offset {
2083            return (stack, None);
2084        }
2085        let mut attrs = self.clone();
2086        let mut last_off = cur + attrs.pos;
2087        while let Some(attr) = attrs.next() {
2088            let Ok(attr) = attr else { break };
2089            match attr {
2090                NdtpaAttrs::Ifindex(val) => {
2091                    if last_off == offset {
2092                        stack.push(("Ifindex", last_off));
2093                        break;
2094                    }
2095                }
2096                NdtpaAttrs::Refcnt(val) => {
2097                    if last_off == offset {
2098                        stack.push(("Refcnt", last_off));
2099                        break;
2100                    }
2101                }
2102                NdtpaAttrs::ReachableTime(val) => {
2103                    if last_off == offset {
2104                        stack.push(("ReachableTime", last_off));
2105                        break;
2106                    }
2107                }
2108                NdtpaAttrs::BaseReachableTime(val) => {
2109                    if last_off == offset {
2110                        stack.push(("BaseReachableTime", last_off));
2111                        break;
2112                    }
2113                }
2114                NdtpaAttrs::RetransTime(val) => {
2115                    if last_off == offset {
2116                        stack.push(("RetransTime", last_off));
2117                        break;
2118                    }
2119                }
2120                NdtpaAttrs::GcStaletime(val) => {
2121                    if last_off == offset {
2122                        stack.push(("GcStaletime", last_off));
2123                        break;
2124                    }
2125                }
2126                NdtpaAttrs::DelayProbeTime(val) => {
2127                    if last_off == offset {
2128                        stack.push(("DelayProbeTime", last_off));
2129                        break;
2130                    }
2131                }
2132                NdtpaAttrs::QueueLen(val) => {
2133                    if last_off == offset {
2134                        stack.push(("QueueLen", last_off));
2135                        break;
2136                    }
2137                }
2138                NdtpaAttrs::AppProbes(val) => {
2139                    if last_off == offset {
2140                        stack.push(("AppProbes", last_off));
2141                        break;
2142                    }
2143                }
2144                NdtpaAttrs::UcastProbes(val) => {
2145                    if last_off == offset {
2146                        stack.push(("UcastProbes", last_off));
2147                        break;
2148                    }
2149                }
2150                NdtpaAttrs::McastProbes(val) => {
2151                    if last_off == offset {
2152                        stack.push(("McastProbes", last_off));
2153                        break;
2154                    }
2155                }
2156                NdtpaAttrs::AnycastDelay(val) => {
2157                    if last_off == offset {
2158                        stack.push(("AnycastDelay", last_off));
2159                        break;
2160                    }
2161                }
2162                NdtpaAttrs::ProxyDelay(val) => {
2163                    if last_off == offset {
2164                        stack.push(("ProxyDelay", last_off));
2165                        break;
2166                    }
2167                }
2168                NdtpaAttrs::ProxyQlen(val) => {
2169                    if last_off == offset {
2170                        stack.push(("ProxyQlen", last_off));
2171                        break;
2172                    }
2173                }
2174                NdtpaAttrs::Locktime(val) => {
2175                    if last_off == offset {
2176                        stack.push(("Locktime", last_off));
2177                        break;
2178                    }
2179                }
2180                NdtpaAttrs::QueueLenbytes(val) => {
2181                    if last_off == offset {
2182                        stack.push(("QueueLenbytes", last_off));
2183                        break;
2184                    }
2185                }
2186                NdtpaAttrs::McastReprobes(val) => {
2187                    if last_off == offset {
2188                        stack.push(("McastReprobes", last_off));
2189                        break;
2190                    }
2191                }
2192                NdtpaAttrs::Pad(val) => {
2193                    if last_off == offset {
2194                        stack.push(("Pad", last_off));
2195                        break;
2196                    }
2197                }
2198                NdtpaAttrs::IntervalProbeTimeMs(val) => {
2199                    if last_off == offset {
2200                        stack.push(("IntervalProbeTimeMs", last_off));
2201                        break;
2202                    }
2203                }
2204                _ => {}
2205            };
2206            last_off = cur + attrs.pos;
2207        }
2208        if !stack.is_empty() {
2209            stack.push(("NdtpaAttrs", cur));
2210        }
2211        (stack, None)
2212    }
2213}
2214pub struct PushNeighbourAttrs<Prev: Pusher> {
2215    pub(crate) prev: Option<Prev>,
2216    pub(crate) header_offset: Option<usize>,
2217}
2218impl<Prev: Pusher> Pusher for PushNeighbourAttrs<Prev> {
2219    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
2220        self.prev.as_mut().unwrap().as_vec_mut()
2221    }
2222    fn as_vec(&self) -> &Vec<u8> {
2223        self.prev.as_ref().unwrap().as_vec()
2224    }
2225}
2226impl<Prev: Pusher> PushNeighbourAttrs<Prev> {
2227    pub fn new(prev: Prev) -> Self {
2228        Self {
2229            prev: Some(prev),
2230            header_offset: None,
2231        }
2232    }
2233    pub fn end_nested(mut self) -> Prev {
2234        let mut prev = self.prev.take().unwrap();
2235        if let Some(header_offset) = &self.header_offset {
2236            finalize_nested_header(prev.as_vec_mut(), *header_offset);
2237        }
2238        prev
2239    }
2240    pub fn push_unspec(mut self, value: &[u8]) -> Self {
2241        push_header(self.as_vec_mut(), 0u16, value.len() as u16);
2242        self.as_vec_mut().extend(value);
2243        self
2244    }
2245    pub fn push_dst(mut self, value: std::net::IpAddr) -> Self {
2246        push_header(self.as_vec_mut(), 1u16, {
2247            match &value {
2248                IpAddr::V4(_) => 4,
2249                IpAddr::V6(_) => 16,
2250            }
2251        } as u16);
2252        encode_ip(self.as_vec_mut(), value);
2253        self
2254    }
2255    pub fn push_lladdr(mut self, value: &[u8]) -> Self {
2256        push_header(self.as_vec_mut(), 2u16, value.len() as u16);
2257        self.as_vec_mut().extend(value);
2258        self
2259    }
2260    pub fn push_cacheinfo(mut self, value: NdaCacheinfo) -> Self {
2261        push_header(self.as_vec_mut(), 3u16, value.as_slice().len() as u16);
2262        self.as_vec_mut().extend(value.as_slice());
2263        self
2264    }
2265    pub fn push_probes(mut self, value: u32) -> Self {
2266        push_header(self.as_vec_mut(), 4u16, 4 as u16);
2267        self.as_vec_mut().extend(value.to_ne_bytes());
2268        self
2269    }
2270    pub fn push_vlan(mut self, value: u16) -> Self {
2271        push_header(self.as_vec_mut(), 5u16, 2 as u16);
2272        self.as_vec_mut().extend(value.to_ne_bytes());
2273        self
2274    }
2275    pub fn push_port(mut self, value: u16) -> Self {
2276        push_header(self.as_vec_mut(), 6u16, 2 as u16);
2277        self.as_vec_mut().extend(value.to_ne_bytes());
2278        self
2279    }
2280    pub fn push_vni(mut self, value: u32) -> Self {
2281        push_header(self.as_vec_mut(), 7u16, 4 as u16);
2282        self.as_vec_mut().extend(value.to_ne_bytes());
2283        self
2284    }
2285    pub fn push_ifindex(mut self, value: u32) -> Self {
2286        push_header(self.as_vec_mut(), 8u16, 4 as u16);
2287        self.as_vec_mut().extend(value.to_ne_bytes());
2288        self
2289    }
2290    pub fn push_master(mut self, value: u32) -> Self {
2291        push_header(self.as_vec_mut(), 9u16, 4 as u16);
2292        self.as_vec_mut().extend(value.to_ne_bytes());
2293        self
2294    }
2295    pub fn push_link_netnsid(mut self, value: i32) -> Self {
2296        push_header(self.as_vec_mut(), 10u16, 4 as u16);
2297        self.as_vec_mut().extend(value.to_ne_bytes());
2298        self
2299    }
2300    pub fn push_src_vni(mut self, value: u32) -> Self {
2301        push_header(self.as_vec_mut(), 11u16, 4 as u16);
2302        self.as_vec_mut().extend(value.to_ne_bytes());
2303        self
2304    }
2305    pub fn push_protocol(mut self, value: u8) -> Self {
2306        push_header(self.as_vec_mut(), 12u16, 1 as u16);
2307        self.as_vec_mut().extend(value.to_ne_bytes());
2308        self
2309    }
2310    pub fn push_nh_id(mut self, value: u32) -> Self {
2311        push_header(self.as_vec_mut(), 13u16, 4 as u16);
2312        self.as_vec_mut().extend(value.to_ne_bytes());
2313        self
2314    }
2315    pub fn push_fdb_ext_attrs(mut self, value: &[u8]) -> Self {
2316        push_header(self.as_vec_mut(), 14u16, value.len() as u16);
2317        self.as_vec_mut().extend(value);
2318        self
2319    }
2320    #[doc = "Associated type: [`NtfExtFlags`] (enum)"]
2321    pub fn push_flags_ext(mut self, value: u32) -> Self {
2322        push_header(self.as_vec_mut(), 15u16, 4 as u16);
2323        self.as_vec_mut().extend(value.to_ne_bytes());
2324        self
2325    }
2326    pub fn push_ndm_state_mask(mut self, value: u16) -> Self {
2327        push_header(self.as_vec_mut(), 16u16, 2 as u16);
2328        self.as_vec_mut().extend(value.to_ne_bytes());
2329        self
2330    }
2331    pub fn push_ndm_flags_mask(mut self, value: u8) -> Self {
2332        push_header(self.as_vec_mut(), 17u16, 1 as u16);
2333        self.as_vec_mut().extend(value.to_ne_bytes());
2334        self
2335    }
2336}
2337impl<Prev: Pusher> Drop for PushNeighbourAttrs<Prev> {
2338    fn drop(&mut self) {
2339        if let Some(prev) = &mut self.prev {
2340            if let Some(header_offset) = &self.header_offset {
2341                finalize_nested_header(prev.as_vec_mut(), *header_offset);
2342            }
2343        }
2344    }
2345}
2346pub struct PushNdtAttrs<Prev: Pusher> {
2347    pub(crate) prev: Option<Prev>,
2348    pub(crate) header_offset: Option<usize>,
2349}
2350impl<Prev: Pusher> Pusher for PushNdtAttrs<Prev> {
2351    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
2352        self.prev.as_mut().unwrap().as_vec_mut()
2353    }
2354    fn as_vec(&self) -> &Vec<u8> {
2355        self.prev.as_ref().unwrap().as_vec()
2356    }
2357}
2358impl<Prev: Pusher> PushNdtAttrs<Prev> {
2359    pub fn new(prev: Prev) -> Self {
2360        Self {
2361            prev: Some(prev),
2362            header_offset: None,
2363        }
2364    }
2365    pub fn end_nested(mut self) -> Prev {
2366        let mut prev = self.prev.take().unwrap();
2367        if let Some(header_offset) = &self.header_offset {
2368            finalize_nested_header(prev.as_vec_mut(), *header_offset);
2369        }
2370        prev
2371    }
2372    pub fn push_name(mut self, value: &CStr) -> Self {
2373        push_header(
2374            self.as_vec_mut(),
2375            1u16,
2376            value.to_bytes_with_nul().len() as u16,
2377        );
2378        self.as_vec_mut().extend(value.to_bytes_with_nul());
2379        self
2380    }
2381    pub fn push_name_bytes(mut self, value: &[u8]) -> Self {
2382        push_header(self.as_vec_mut(), 1u16, (value.len() + 1) as u16);
2383        self.as_vec_mut().extend(value);
2384        self.as_vec_mut().push(0);
2385        self
2386    }
2387    pub fn push_thresh1(mut self, value: u32) -> Self {
2388        push_header(self.as_vec_mut(), 2u16, 4 as u16);
2389        self.as_vec_mut().extend(value.to_ne_bytes());
2390        self
2391    }
2392    pub fn push_thresh2(mut self, value: u32) -> Self {
2393        push_header(self.as_vec_mut(), 3u16, 4 as u16);
2394        self.as_vec_mut().extend(value.to_ne_bytes());
2395        self
2396    }
2397    pub fn push_thresh3(mut self, value: u32) -> Self {
2398        push_header(self.as_vec_mut(), 4u16, 4 as u16);
2399        self.as_vec_mut().extend(value.to_ne_bytes());
2400        self
2401    }
2402    pub fn push_config(mut self, value: NdtConfig) -> Self {
2403        push_header(self.as_vec_mut(), 5u16, value.as_slice().len() as u16);
2404        self.as_vec_mut().extend(value.as_slice());
2405        self
2406    }
2407    pub fn nested_parms(mut self) -> PushNdtpaAttrs<Self> {
2408        let header_offset = push_nested_header(self.as_vec_mut(), 6u16);
2409        PushNdtpaAttrs {
2410            prev: Some(self),
2411            header_offset: Some(header_offset),
2412        }
2413    }
2414    pub fn push_stats(mut self, value: NdtStats) -> Self {
2415        push_header(self.as_vec_mut(), 7u16, value.as_slice().len() as u16);
2416        self.as_vec_mut().extend(value.as_slice());
2417        self
2418    }
2419    pub fn push_gc_interval(mut self, value: u64) -> Self {
2420        push_header(self.as_vec_mut(), 8u16, 8 as u16);
2421        self.as_vec_mut().extend(value.to_ne_bytes());
2422        self
2423    }
2424    pub fn push_pad(mut self, value: &[u8]) -> Self {
2425        push_header(self.as_vec_mut(), 9u16, value.len() as u16);
2426        self.as_vec_mut().extend(value);
2427        self
2428    }
2429}
2430impl<Prev: Pusher> Drop for PushNdtAttrs<Prev> {
2431    fn drop(&mut self) {
2432        if let Some(prev) = &mut self.prev {
2433            if let Some(header_offset) = &self.header_offset {
2434                finalize_nested_header(prev.as_vec_mut(), *header_offset);
2435            }
2436        }
2437    }
2438}
2439pub struct PushNdtpaAttrs<Prev: Pusher> {
2440    pub(crate) prev: Option<Prev>,
2441    pub(crate) header_offset: Option<usize>,
2442}
2443impl<Prev: Pusher> Pusher for PushNdtpaAttrs<Prev> {
2444    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
2445        self.prev.as_mut().unwrap().as_vec_mut()
2446    }
2447    fn as_vec(&self) -> &Vec<u8> {
2448        self.prev.as_ref().unwrap().as_vec()
2449    }
2450}
2451impl<Prev: Pusher> PushNdtpaAttrs<Prev> {
2452    pub fn new(prev: Prev) -> Self {
2453        Self {
2454            prev: Some(prev),
2455            header_offset: None,
2456        }
2457    }
2458    pub fn end_nested(mut self) -> Prev {
2459        let mut prev = self.prev.take().unwrap();
2460        if let Some(header_offset) = &self.header_offset {
2461            finalize_nested_header(prev.as_vec_mut(), *header_offset);
2462        }
2463        prev
2464    }
2465    pub fn push_ifindex(mut self, value: u32) -> Self {
2466        push_header(self.as_vec_mut(), 1u16, 4 as u16);
2467        self.as_vec_mut().extend(value.to_ne_bytes());
2468        self
2469    }
2470    pub fn push_refcnt(mut self, value: u32) -> Self {
2471        push_header(self.as_vec_mut(), 2u16, 4 as u16);
2472        self.as_vec_mut().extend(value.to_ne_bytes());
2473        self
2474    }
2475    pub fn push_reachable_time(mut self, value: u64) -> Self {
2476        push_header(self.as_vec_mut(), 3u16, 8 as u16);
2477        self.as_vec_mut().extend(value.to_ne_bytes());
2478        self
2479    }
2480    pub fn push_base_reachable_time(mut self, value: u64) -> Self {
2481        push_header(self.as_vec_mut(), 4u16, 8 as u16);
2482        self.as_vec_mut().extend(value.to_ne_bytes());
2483        self
2484    }
2485    pub fn push_retrans_time(mut self, value: u64) -> Self {
2486        push_header(self.as_vec_mut(), 5u16, 8 as u16);
2487        self.as_vec_mut().extend(value.to_ne_bytes());
2488        self
2489    }
2490    pub fn push_gc_staletime(mut self, value: u64) -> Self {
2491        push_header(self.as_vec_mut(), 6u16, 8 as u16);
2492        self.as_vec_mut().extend(value.to_ne_bytes());
2493        self
2494    }
2495    pub fn push_delay_probe_time(mut self, value: u64) -> Self {
2496        push_header(self.as_vec_mut(), 7u16, 8 as u16);
2497        self.as_vec_mut().extend(value.to_ne_bytes());
2498        self
2499    }
2500    pub fn push_queue_len(mut self, value: u32) -> Self {
2501        push_header(self.as_vec_mut(), 8u16, 4 as u16);
2502        self.as_vec_mut().extend(value.to_ne_bytes());
2503        self
2504    }
2505    pub fn push_app_probes(mut self, value: u32) -> Self {
2506        push_header(self.as_vec_mut(), 9u16, 4 as u16);
2507        self.as_vec_mut().extend(value.to_ne_bytes());
2508        self
2509    }
2510    pub fn push_ucast_probes(mut self, value: u32) -> Self {
2511        push_header(self.as_vec_mut(), 10u16, 4 as u16);
2512        self.as_vec_mut().extend(value.to_ne_bytes());
2513        self
2514    }
2515    pub fn push_mcast_probes(mut self, value: u32) -> Self {
2516        push_header(self.as_vec_mut(), 11u16, 4 as u16);
2517        self.as_vec_mut().extend(value.to_ne_bytes());
2518        self
2519    }
2520    pub fn push_anycast_delay(mut self, value: u64) -> Self {
2521        push_header(self.as_vec_mut(), 12u16, 8 as u16);
2522        self.as_vec_mut().extend(value.to_ne_bytes());
2523        self
2524    }
2525    pub fn push_proxy_delay(mut self, value: u64) -> Self {
2526        push_header(self.as_vec_mut(), 13u16, 8 as u16);
2527        self.as_vec_mut().extend(value.to_ne_bytes());
2528        self
2529    }
2530    pub fn push_proxy_qlen(mut self, value: u32) -> Self {
2531        push_header(self.as_vec_mut(), 14u16, 4 as u16);
2532        self.as_vec_mut().extend(value.to_ne_bytes());
2533        self
2534    }
2535    pub fn push_locktime(mut self, value: u64) -> Self {
2536        push_header(self.as_vec_mut(), 15u16, 8 as u16);
2537        self.as_vec_mut().extend(value.to_ne_bytes());
2538        self
2539    }
2540    pub fn push_queue_lenbytes(mut self, value: u32) -> Self {
2541        push_header(self.as_vec_mut(), 16u16, 4 as u16);
2542        self.as_vec_mut().extend(value.to_ne_bytes());
2543        self
2544    }
2545    pub fn push_mcast_reprobes(mut self, value: u32) -> Self {
2546        push_header(self.as_vec_mut(), 17u16, 4 as u16);
2547        self.as_vec_mut().extend(value.to_ne_bytes());
2548        self
2549    }
2550    pub fn push_pad(mut self, value: &[u8]) -> Self {
2551        push_header(self.as_vec_mut(), 18u16, value.len() as u16);
2552        self.as_vec_mut().extend(value);
2553        self
2554    }
2555    pub fn push_interval_probe_time_ms(mut self, value: u64) -> Self {
2556        push_header(self.as_vec_mut(), 19u16, 8 as u16);
2557        self.as_vec_mut().extend(value.to_ne_bytes());
2558        self
2559    }
2560}
2561impl<Prev: Pusher> Drop for PushNdtpaAttrs<Prev> {
2562    fn drop(&mut self) {
2563        if let Some(prev) = &mut self.prev {
2564            if let Some(header_offset) = &self.header_offset {
2565                finalize_nested_header(prev.as_vec_mut(), *header_offset);
2566            }
2567        }
2568    }
2569}
2570#[doc = "Add new neighbour entry\n\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\n"]
2571#[derive(Debug)]
2572pub struct OpNewneighDo<'r> {
2573    request: Request<'r>,
2574}
2575impl<'r> OpNewneighDo<'r> {
2576    pub fn new(mut request: Request<'r>, header: &Ndmsg) -> Self {
2577        Self::write_header(request.buf_mut(), header);
2578        Self { request: request }
2579    }
2580    pub fn encode_request<'buf>(
2581        buf: &'buf mut Vec<u8>,
2582        header: &Ndmsg,
2583    ) -> PushNeighbourAttrs<&'buf mut Vec<u8>> {
2584        Self::write_header(buf, header);
2585        PushNeighbourAttrs::new(buf)
2586    }
2587    pub fn encode(&mut self) -> PushNeighbourAttrs<&mut Vec<u8>> {
2588        PushNeighbourAttrs::new(self.request.buf_mut())
2589    }
2590    pub fn into_encoder(self) -> PushNeighbourAttrs<RequestBuf<'r>> {
2591        PushNeighbourAttrs::new(self.request.buf)
2592    }
2593    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndmsg, IterableNeighbourAttrs<'a>) {
2594        let (header, attrs) = buf.split_at(buf.len().min(Ndmsg::len()));
2595        (
2596            Ndmsg::new_from_slice(header).unwrap_or_default(),
2597            IterableNeighbourAttrs::with_loc(attrs, buf.as_ptr() as usize),
2598        )
2599    }
2600    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ndmsg) {
2601        prev.as_vec_mut().extend(header.as_slice());
2602    }
2603}
2604impl NetlinkRequest for OpNewneighDo<'_> {
2605    fn protocol(&self) -> Protocol {
2606        Protocol::Raw {
2607            protonum: 0u16,
2608            request_type: 28u16,
2609        }
2610    }
2611    fn flags(&self) -> u16 {
2612        self.request.flags
2613    }
2614    fn payload(&self) -> &[u8] {
2615        self.request.buf()
2616    }
2617    type ReplyType<'buf> = (Ndmsg, IterableNeighbourAttrs<'buf>);
2618    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2619        Self::decode_request(buf)
2620    }
2621    fn lookup(
2622        buf: &[u8],
2623        offset: usize,
2624        missing_type: Option<u16>,
2625    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2626        Self::decode_request(buf)
2627            .1
2628            .lookup_attr(offset, missing_type)
2629    }
2630}
2631#[doc = "Remove an existing neighbour entry\n\nRequest attributes:\n- [.push_dst()](PushNeighbourAttrs::push_dst)\n- [.push_ifindex()](PushNeighbourAttrs::push_ifindex)\n\n"]
2632#[derive(Debug)]
2633pub struct OpDelneighDo<'r> {
2634    request: Request<'r>,
2635}
2636impl<'r> OpDelneighDo<'r> {
2637    pub fn new(mut request: Request<'r>, header: &Ndmsg) -> Self {
2638        Self::write_header(request.buf_mut(), header);
2639        Self { request: request }
2640    }
2641    pub fn encode_request<'buf>(
2642        buf: &'buf mut Vec<u8>,
2643        header: &Ndmsg,
2644    ) -> PushNeighbourAttrs<&'buf mut Vec<u8>> {
2645        Self::write_header(buf, header);
2646        PushNeighbourAttrs::new(buf)
2647    }
2648    pub fn encode(&mut self) -> PushNeighbourAttrs<&mut Vec<u8>> {
2649        PushNeighbourAttrs::new(self.request.buf_mut())
2650    }
2651    pub fn into_encoder(self) -> PushNeighbourAttrs<RequestBuf<'r>> {
2652        PushNeighbourAttrs::new(self.request.buf)
2653    }
2654    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndmsg, IterableNeighbourAttrs<'a>) {
2655        let (header, attrs) = buf.split_at(buf.len().min(Ndmsg::len()));
2656        (
2657            Ndmsg::new_from_slice(header).unwrap_or_default(),
2658            IterableNeighbourAttrs::with_loc(attrs, buf.as_ptr() as usize),
2659        )
2660    }
2661    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ndmsg) {
2662        prev.as_vec_mut().extend(header.as_slice());
2663    }
2664}
2665impl NetlinkRequest for OpDelneighDo<'_> {
2666    fn protocol(&self) -> Protocol {
2667        Protocol::Raw {
2668            protonum: 0u16,
2669            request_type: 29u16,
2670        }
2671    }
2672    fn flags(&self) -> u16 {
2673        self.request.flags
2674    }
2675    fn payload(&self) -> &[u8] {
2676        self.request.buf()
2677    }
2678    type ReplyType<'buf> = (Ndmsg, IterableNeighbourAttrs<'buf>);
2679    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2680        Self::decode_request(buf)
2681    }
2682    fn lookup(
2683        buf: &[u8],
2684        offset: usize,
2685        missing_type: Option<u16>,
2686    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2687        Self::decode_request(buf)
2688            .1
2689            .lookup_attr(offset, missing_type)
2690    }
2691}
2692#[doc = "Get or dump neighbour entries\n\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\n"]
2693#[derive(Debug)]
2694pub struct OpGetneighDump<'r> {
2695    request: Request<'r>,
2696}
2697impl<'r> OpGetneighDump<'r> {
2698    pub fn new(mut request: Request<'r>, header: &Ndmsg) -> Self {
2699        Self::write_header(request.buf_mut(), header);
2700        Self {
2701            request: request.set_dump(),
2702        }
2703    }
2704    pub fn encode_request<'buf>(
2705        buf: &'buf mut Vec<u8>,
2706        header: &Ndmsg,
2707    ) -> PushNeighbourAttrs<&'buf mut Vec<u8>> {
2708        Self::write_header(buf, header);
2709        PushNeighbourAttrs::new(buf)
2710    }
2711    pub fn encode(&mut self) -> PushNeighbourAttrs<&mut Vec<u8>> {
2712        PushNeighbourAttrs::new(self.request.buf_mut())
2713    }
2714    pub fn into_encoder(self) -> PushNeighbourAttrs<RequestBuf<'r>> {
2715        PushNeighbourAttrs::new(self.request.buf)
2716    }
2717    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndmsg, IterableNeighbourAttrs<'a>) {
2718        let (header, attrs) = buf.split_at(buf.len().min(Ndmsg::len()));
2719        (
2720            Ndmsg::new_from_slice(header).unwrap_or_default(),
2721            IterableNeighbourAttrs::with_loc(attrs, buf.as_ptr() as usize),
2722        )
2723    }
2724    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ndmsg) {
2725        prev.as_vec_mut().extend(header.as_slice());
2726    }
2727}
2728impl NetlinkRequest for OpGetneighDump<'_> {
2729    fn protocol(&self) -> Protocol {
2730        Protocol::Raw {
2731            protonum: 0u16,
2732            request_type: 30u16,
2733        }
2734    }
2735    fn flags(&self) -> u16 {
2736        self.request.flags
2737    }
2738    fn payload(&self) -> &[u8] {
2739        self.request.buf()
2740    }
2741    type ReplyType<'buf> = (Ndmsg, IterableNeighbourAttrs<'buf>);
2742    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2743        Self::decode_request(buf)
2744    }
2745    fn lookup(
2746        buf: &[u8],
2747        offset: usize,
2748        missing_type: Option<u16>,
2749    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2750        Self::decode_request(buf)
2751            .1
2752            .lookup_attr(offset, missing_type)
2753    }
2754}
2755#[doc = "Get or dump neighbour entries\n\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\n"]
2756#[derive(Debug)]
2757pub struct OpGetneighDo<'r> {
2758    request: Request<'r>,
2759}
2760impl<'r> OpGetneighDo<'r> {
2761    pub fn new(mut request: Request<'r>, header: &Ndmsg) -> Self {
2762        Self::write_header(request.buf_mut(), header);
2763        Self { request: request }
2764    }
2765    pub fn encode_request<'buf>(
2766        buf: &'buf mut Vec<u8>,
2767        header: &Ndmsg,
2768    ) -> PushNeighbourAttrs<&'buf mut Vec<u8>> {
2769        Self::write_header(buf, header);
2770        PushNeighbourAttrs::new(buf)
2771    }
2772    pub fn encode(&mut self) -> PushNeighbourAttrs<&mut Vec<u8>> {
2773        PushNeighbourAttrs::new(self.request.buf_mut())
2774    }
2775    pub fn into_encoder(self) -> PushNeighbourAttrs<RequestBuf<'r>> {
2776        PushNeighbourAttrs::new(self.request.buf)
2777    }
2778    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndmsg, IterableNeighbourAttrs<'a>) {
2779        let (header, attrs) = buf.split_at(buf.len().min(Ndmsg::len()));
2780        (
2781            Ndmsg::new_from_slice(header).unwrap_or_default(),
2782            IterableNeighbourAttrs::with_loc(attrs, buf.as_ptr() as usize),
2783        )
2784    }
2785    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ndmsg) {
2786        prev.as_vec_mut().extend(header.as_slice());
2787    }
2788}
2789impl NetlinkRequest for OpGetneighDo<'_> {
2790    fn protocol(&self) -> Protocol {
2791        Protocol::Raw {
2792            protonum: 0u16,
2793            request_type: 30u16,
2794        }
2795    }
2796    fn flags(&self) -> u16 {
2797        self.request.flags
2798    }
2799    fn payload(&self) -> &[u8] {
2800        self.request.buf()
2801    }
2802    type ReplyType<'buf> = (Ndmsg, IterableNeighbourAttrs<'buf>);
2803    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2804        Self::decode_request(buf)
2805    }
2806    fn lookup(
2807        buf: &[u8],
2808        offset: usize,
2809        missing_type: Option<u16>,
2810    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2811        Self::decode_request(buf)
2812            .1
2813            .lookup_attr(offset, missing_type)
2814    }
2815}
2816#[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\n"]
2817#[derive(Debug)]
2818pub struct OpGetneightblDump<'r> {
2819    request: Request<'r>,
2820}
2821impl<'r> OpGetneightblDump<'r> {
2822    pub fn new(mut request: Request<'r>, header: &Ndtmsg) -> Self {
2823        Self::write_header(request.buf_mut(), header);
2824        Self {
2825            request: request.set_dump(),
2826        }
2827    }
2828    pub fn encode_request<'buf>(
2829        buf: &'buf mut Vec<u8>,
2830        header: &Ndtmsg,
2831    ) -> PushNdtAttrs<&'buf mut Vec<u8>> {
2832        Self::write_header(buf, header);
2833        PushNdtAttrs::new(buf)
2834    }
2835    pub fn encode(&mut self) -> PushNdtAttrs<&mut Vec<u8>> {
2836        PushNdtAttrs::new(self.request.buf_mut())
2837    }
2838    pub fn into_encoder(self) -> PushNdtAttrs<RequestBuf<'r>> {
2839        PushNdtAttrs::new(self.request.buf)
2840    }
2841    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndtmsg, IterableNdtAttrs<'a>) {
2842        let (header, attrs) = buf.split_at(buf.len().min(Ndtmsg::len()));
2843        (
2844            Ndtmsg::new_from_slice(header).unwrap_or_default(),
2845            IterableNdtAttrs::with_loc(attrs, buf.as_ptr() as usize),
2846        )
2847    }
2848    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ndtmsg) {
2849        prev.as_vec_mut().extend(header.as_slice());
2850    }
2851}
2852impl NetlinkRequest for OpGetneightblDump<'_> {
2853    fn protocol(&self) -> Protocol {
2854        Protocol::Raw {
2855            protonum: 0u16,
2856            request_type: 66u16,
2857        }
2858    }
2859    fn flags(&self) -> u16 {
2860        self.request.flags
2861    }
2862    fn payload(&self) -> &[u8] {
2863        self.request.buf()
2864    }
2865    type ReplyType<'buf> = (Ndtmsg, IterableNdtAttrs<'buf>);
2866    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2867        Self::decode_request(buf)
2868    }
2869    fn lookup(
2870        buf: &[u8],
2871        offset: usize,
2872        missing_type: Option<u16>,
2873    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2874        Self::decode_request(buf)
2875            .1
2876            .lookup_attr(offset, missing_type)
2877    }
2878}
2879#[doc = "Set neighbour tables\n\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\n"]
2880#[derive(Debug)]
2881pub struct OpSetneightblDo<'r> {
2882    request: Request<'r>,
2883}
2884impl<'r> OpSetneightblDo<'r> {
2885    pub fn new(mut request: Request<'r>, header: &Ndtmsg) -> Self {
2886        Self::write_header(request.buf_mut(), header);
2887        Self { request: request }
2888    }
2889    pub fn encode_request<'buf>(
2890        buf: &'buf mut Vec<u8>,
2891        header: &Ndtmsg,
2892    ) -> PushNdtAttrs<&'buf mut Vec<u8>> {
2893        Self::write_header(buf, header);
2894        PushNdtAttrs::new(buf)
2895    }
2896    pub fn encode(&mut self) -> PushNdtAttrs<&mut Vec<u8>> {
2897        PushNdtAttrs::new(self.request.buf_mut())
2898    }
2899    pub fn into_encoder(self) -> PushNdtAttrs<RequestBuf<'r>> {
2900        PushNdtAttrs::new(self.request.buf)
2901    }
2902    pub fn decode_request<'a>(buf: &'a [u8]) -> (Ndtmsg, IterableNdtAttrs<'a>) {
2903        let (header, attrs) = buf.split_at(buf.len().min(Ndtmsg::len()));
2904        (
2905            Ndtmsg::new_from_slice(header).unwrap_or_default(),
2906            IterableNdtAttrs::with_loc(attrs, buf.as_ptr() as usize),
2907        )
2908    }
2909    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ndtmsg) {
2910        prev.as_vec_mut().extend(header.as_slice());
2911    }
2912}
2913impl NetlinkRequest for OpSetneightblDo<'_> {
2914    fn protocol(&self) -> Protocol {
2915        Protocol::Raw {
2916            protonum: 0u16,
2917            request_type: 67u16,
2918        }
2919    }
2920    fn flags(&self) -> u16 {
2921        self.request.flags
2922    }
2923    fn payload(&self) -> &[u8] {
2924        self.request.buf()
2925    }
2926    type ReplyType<'buf> = (Ndtmsg, IterableNdtAttrs<'buf>);
2927    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2928        Self::decode_request(buf)
2929    }
2930    fn lookup(
2931        buf: &[u8],
2932        offset: usize,
2933        missing_type: Option<u16>,
2934    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2935        Self::decode_request(buf)
2936            .1
2937            .lookup_attr(offset, missing_type)
2938    }
2939}
2940#[derive(Debug)]
2941pub struct ChainedFinal<'a> {
2942    inner: Chained<'a>,
2943}
2944#[derive(Debug)]
2945pub struct Chained<'a> {
2946    buf: RequestBuf<'a>,
2947    first_seq: u32,
2948    lookups: Vec<(&'static str, LookupFn)>,
2949    last_header_offset: usize,
2950    last_kind: Option<RequestInfo>,
2951}
2952impl<'a> ChainedFinal<'a> {
2953    pub fn into_chained(self) -> Chained<'a> {
2954        self.inner
2955    }
2956    pub fn buf(&self) -> &Vec<u8> {
2957        self.inner.buf()
2958    }
2959    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2960        self.inner.buf_mut()
2961    }
2962    fn get_index(&self, seq: u32) -> Option<u32> {
2963        let min = self.inner.first_seq;
2964        let max = min.wrapping_add(self.inner.lookups.len() as u32);
2965        return if min <= max {
2966            (min..max).contains(&seq).then(|| seq - min)
2967        } else if min <= seq {
2968            Some(seq - min)
2969        } else if seq < max {
2970            Some(u32::MAX - min + seq)
2971        } else {
2972            None
2973        };
2974    }
2975}
2976impl crate::traits::NetlinkChained for ChainedFinal<'_> {
2977    fn protonum(&self) -> u16 {
2978        PROTONUM
2979    }
2980    fn payload(&self) -> &[u8] {
2981        self.buf()
2982    }
2983    fn chain_len(&self) -> usize {
2984        self.inner.lookups.len()
2985    }
2986    fn get_index(&self, seq: u32) -> Option<usize> {
2987        self.get_index(seq).map(|n| n as usize)
2988    }
2989    fn name(&self, index: usize) -> &'static str {
2990        self.inner.lookups[index].0
2991    }
2992    fn lookup(&self, index: usize) -> LookupFn {
2993        self.inner.lookups[index].1
2994    }
2995}
2996impl Chained<'static> {
2997    pub fn new(first_seq: u32) -> Self {
2998        Self::new_from_buf(Vec::new(), first_seq)
2999    }
3000    pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
3001        Self {
3002            buf: RequestBuf::Own(buf),
3003            first_seq,
3004            lookups: Vec::new(),
3005            last_header_offset: 0,
3006            last_kind: None,
3007        }
3008    }
3009    pub fn into_buf(self) -> Vec<u8> {
3010        match self.buf {
3011            RequestBuf::Own(buf) => buf,
3012            _ => unreachable!(),
3013        }
3014    }
3015}
3016impl<'a> Chained<'a> {
3017    pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
3018        Self {
3019            buf: RequestBuf::Ref(buf),
3020            first_seq,
3021            lookups: Vec::new(),
3022            last_header_offset: 0,
3023            last_kind: None,
3024        }
3025    }
3026    pub fn finalize(mut self) -> ChainedFinal<'a> {
3027        self.update_header();
3028        ChainedFinal { inner: self }
3029    }
3030    pub fn request(&mut self) -> Request<'_> {
3031        self.update_header();
3032        self.last_header_offset = self.buf().len();
3033        self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
3034        let mut request = Request::new_extend(self.buf.buf_mut());
3035        self.last_kind = None;
3036        request.writeback = Some(&mut self.last_kind);
3037        request
3038    }
3039    pub fn buf(&self) -> &Vec<u8> {
3040        self.buf.buf()
3041    }
3042    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3043        self.buf.buf_mut()
3044    }
3045    fn update_header(&mut self) {
3046        let Some(RequestInfo {
3047            protocol,
3048            flags,
3049            name,
3050            lookup,
3051        }) = self.last_kind
3052        else {
3053            if !self.buf().is_empty() {
3054                assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
3055                self.buf.buf_mut().truncate(self.last_header_offset);
3056            }
3057            return;
3058        };
3059        let header_offset = self.last_header_offset;
3060        let request_type = match protocol {
3061            Protocol::Raw { request_type, .. } => request_type,
3062            Protocol::Generic(_) => unreachable!(),
3063        };
3064        let index = self.lookups.len();
3065        let seq = self.first_seq.wrapping_add(index as u32);
3066        self.lookups.push((name, lookup));
3067        let buf = self.buf_mut();
3068        align(buf);
3069        let header = Nlmsghdr {
3070            len: (buf.len() - header_offset) as u32,
3071            r#type: request_type,
3072            flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
3073            seq,
3074            pid: 0,
3075        };
3076        buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
3077    }
3078}
3079use crate::traits::LookupFn;
3080use crate::utils::RequestBuf;
3081#[derive(Debug)]
3082pub struct Request<'buf> {
3083    buf: RequestBuf<'buf>,
3084    flags: u16,
3085    writeback: Option<&'buf mut Option<RequestInfo>>,
3086}
3087#[allow(unused)]
3088#[derive(Debug, Clone)]
3089pub struct RequestInfo {
3090    protocol: Protocol,
3091    flags: u16,
3092    name: &'static str,
3093    lookup: LookupFn,
3094}
3095impl Request<'static> {
3096    pub fn new() -> Self {
3097        Self::new_from_buf(Vec::new())
3098    }
3099    pub fn new_from_buf(buf: Vec<u8>) -> Self {
3100        Self {
3101            flags: 0,
3102            buf: RequestBuf::Own(buf),
3103            writeback: None,
3104        }
3105    }
3106    pub fn into_buf(self) -> Vec<u8> {
3107        match self.buf {
3108            RequestBuf::Own(buf) => buf,
3109            _ => unreachable!(),
3110        }
3111    }
3112}
3113impl<'buf> Request<'buf> {
3114    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
3115        buf.clear();
3116        Self::new_extend(buf)
3117    }
3118    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
3119        Self {
3120            flags: 0,
3121            buf: RequestBuf::Ref(buf),
3122            writeback: None,
3123        }
3124    }
3125    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
3126        let Some(writeback) = &mut self.writeback else {
3127            return;
3128        };
3129        **writeback = Some(RequestInfo {
3130            protocol,
3131            flags: self.flags,
3132            name,
3133            lookup,
3134        })
3135    }
3136    pub fn buf(&self) -> &Vec<u8> {
3137        self.buf.buf()
3138    }
3139    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3140        self.buf.buf_mut()
3141    }
3142    #[doc = "Set `NLM_F_CREATE` flag"]
3143    pub fn set_create(mut self) -> Self {
3144        self.flags |= consts::NLM_F_CREATE as u16;
3145        self
3146    }
3147    #[doc = "Set `NLM_F_EXCL` flag"]
3148    pub fn set_excl(mut self) -> Self {
3149        self.flags |= consts::NLM_F_EXCL as u16;
3150        self
3151    }
3152    #[doc = "Set `NLM_F_REPLACE` flag"]
3153    pub fn set_replace(mut self) -> Self {
3154        self.flags |= consts::NLM_F_REPLACE as u16;
3155        self
3156    }
3157    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
3158    pub fn set_change(self) -> Self {
3159        self.set_create().set_replace()
3160    }
3161    #[doc = "Set `NLM_F_APPEND` flag"]
3162    pub fn set_append(mut self) -> Self {
3163        self.flags |= consts::NLM_F_APPEND as u16;
3164        self
3165    }
3166    #[doc = "Set `self.flags |= flags`"]
3167    pub fn set_flags(mut self, flags: u16) -> Self {
3168        self.flags |= flags;
3169        self
3170    }
3171    #[doc = "Set `self.flags ^= self.flags & flags`"]
3172    pub fn unset_flags(mut self, flags: u16) -> Self {
3173        self.flags ^= self.flags & flags;
3174        self
3175    }
3176    #[doc = "Set `NLM_F_DUMP` flag"]
3177    fn set_dump(mut self) -> Self {
3178        self.flags |= consts::NLM_F_DUMP as u16;
3179        self
3180    }
3181    #[doc = "Add new neighbour entry\n\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\n"]
3182    pub fn op_newneigh_do(self, header: &Ndmsg) -> OpNewneighDo<'buf> {
3183        let mut res = OpNewneighDo::new(self, header);
3184        res.request
3185            .do_writeback(res.protocol(), "op-newneigh-do", OpNewneighDo::lookup);
3186        res
3187    }
3188    #[doc = "Remove an existing neighbour entry\n\nRequest attributes:\n- [.push_dst()](PushNeighbourAttrs::push_dst)\n- [.push_ifindex()](PushNeighbourAttrs::push_ifindex)\n\n"]
3189    pub fn op_delneigh_do(self, header: &Ndmsg) -> OpDelneighDo<'buf> {
3190        let mut res = OpDelneighDo::new(self, header);
3191        res.request
3192            .do_writeback(res.protocol(), "op-delneigh-do", OpDelneighDo::lookup);
3193        res
3194    }
3195    #[doc = "Get or dump neighbour entries\n\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\n"]
3196    pub fn op_getneigh_dump(self, header: &Ndmsg) -> OpGetneighDump<'buf> {
3197        let mut res = OpGetneighDump::new(self, header);
3198        res.request
3199            .do_writeback(res.protocol(), "op-getneigh-dump", OpGetneighDump::lookup);
3200        res
3201    }
3202    #[doc = "Get or dump neighbour entries\n\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\n"]
3203    pub fn op_getneigh_do(self, header: &Ndmsg) -> OpGetneighDo<'buf> {
3204        let mut res = OpGetneighDo::new(self, header);
3205        res.request
3206            .do_writeback(res.protocol(), "op-getneigh-do", OpGetneighDo::lookup);
3207        res
3208    }
3209    #[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\n"]
3210    pub fn op_getneightbl_dump(self, header: &Ndtmsg) -> OpGetneightblDump<'buf> {
3211        let mut res = OpGetneightblDump::new(self, header);
3212        res.request.do_writeback(
3213            res.protocol(),
3214            "op-getneightbl-dump",
3215            OpGetneightblDump::lookup,
3216        );
3217        res
3218    }
3219    #[doc = "Set neighbour tables\n\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\n"]
3220    pub fn op_setneightbl_do(self, header: &Ndtmsg) -> OpSetneightblDo<'buf> {
3221        let mut res = OpSetneightblDo::new(self, header);
3222        res.request
3223            .do_writeback(res.protocol(), "op-setneightbl-do", OpSetneightblDo::lookup);
3224        res
3225    }
3226}
3227#[cfg(test)]
3228mod generated_tests {
3229    use super::*;
3230    #[test]
3231    fn tests() {
3232        let _ = IterableNdtAttrs::get_config;
3233        let _ = IterableNdtAttrs::get_gc_interval;
3234        let _ = IterableNdtAttrs::get_name;
3235        let _ = IterableNdtAttrs::get_parms;
3236        let _ = IterableNdtAttrs::get_stats;
3237        let _ = IterableNdtAttrs::get_thresh1;
3238        let _ = IterableNdtAttrs::get_thresh2;
3239        let _ = IterableNdtAttrs::get_thresh3;
3240        let _ = IterableNeighbourAttrs::get_dst;
3241        let _ = IterableNeighbourAttrs::get_fdb_ext_attrs;
3242        let _ = IterableNeighbourAttrs::get_flags_ext;
3243        let _ = IterableNeighbourAttrs::get_ifindex;
3244        let _ = IterableNeighbourAttrs::get_lladdr;
3245        let _ = IterableNeighbourAttrs::get_master;
3246        let _ = IterableNeighbourAttrs::get_nh_id;
3247        let _ = IterableNeighbourAttrs::get_port;
3248        let _ = IterableNeighbourAttrs::get_probes;
3249        let _ = IterableNeighbourAttrs::get_protocol;
3250        let _ = IterableNeighbourAttrs::get_vlan;
3251        let _ = IterableNeighbourAttrs::get_vni;
3252        let _ = PushNdtAttrs::<&mut Vec<u8>>::nested_parms;
3253        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_gc_interval;
3254        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_name;
3255        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_thresh1;
3256        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_thresh2;
3257        let _ = PushNdtAttrs::<&mut Vec<u8>>::push_thresh3;
3258        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_dst;
3259        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_fdb_ext_attrs;
3260        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_flags_ext;
3261        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_ifindex;
3262        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_lladdr;
3263        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_master;
3264        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_nh_id;
3265        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_port;
3266        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_probes;
3267        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_protocol;
3268        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_vlan;
3269        let _ = PushNeighbourAttrs::<&mut Vec<u8>>::push_vni;
3270    }
3271}