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