1#![doc = "Address configuration over rtnetlink\\."]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &str = "rt-addr";
17pub const PROTONAME_CSTR: &CStr = c"rt-addr";
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 IfaFlags {
22 Secondary = 1 << 0,
23 Nodad = 1 << 1,
24 Optimistic = 1 << 2,
25 Dadfailed = 1 << 3,
26 Homeaddress = 1 << 4,
27 Deprecated = 1 << 5,
28 Tentative = 1 << 6,
29 Permanent = 1 << 7,
30 Managetempaddr = 1 << 8,
31 Noprefixroute = 1 << 9,
32 Mcautojoin = 1 << 10,
33 StablePrivacy = 1 << 11,
34}
35impl IfaFlags {
36 pub fn from_value(value: u64) -> Option<Self> {
37 Some(match value {
38 n if n == 1 << 0 => Self::Secondary,
39 n if n == 1 << 1 => Self::Nodad,
40 n if n == 1 << 2 => Self::Optimistic,
41 n if n == 1 << 3 => Self::Dadfailed,
42 n if n == 1 << 4 => Self::Homeaddress,
43 n if n == 1 << 5 => Self::Deprecated,
44 n if n == 1 << 6 => Self::Tentative,
45 n if n == 1 << 7 => Self::Permanent,
46 n if n == 1 << 8 => Self::Managetempaddr,
47 n if n == 1 << 9 => Self::Noprefixroute,
48 n if n == 1 << 10 => Self::Mcautojoin,
49 n if n == 1 << 11 => Self::StablePrivacy,
50 _ => return None,
51 })
52 }
53}
54#[repr(C, packed(4))]
55pub struct Ifaddrmsg {
56 pub ifa_family: u8,
57 pub ifa_prefixlen: u8,
58 #[doc = "Associated type: [`IfaFlags`] (1 bit per enumeration)"]
59 pub ifa_flags: u8,
60 pub ifa_scope: u8,
61 pub ifa_index: u32,
62}
63impl Clone for Ifaddrmsg {
64 fn clone(&self) -> Self {
65 Self::new_from_array(*self.as_array())
66 }
67}
68#[doc = "Create zero-initialized struct"]
69impl Default for Ifaddrmsg {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74impl Ifaddrmsg {
75 #[doc = "Create zero-initialized struct"]
76 pub fn new() -> Self {
77 Self::new_from_array([0u8; Self::len()])
78 }
79 #[doc = "Copy from contents from slice"]
80 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
81 if other.len() != Self::len() {
82 return None;
83 }
84 let mut buf = [0u8; Self::len()];
85 buf.clone_from_slice(other);
86 Some(Self::new_from_array(buf))
87 }
88 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
89 pub fn new_from_zeroed(other: &[u8]) -> Self {
90 let mut buf = [0u8; Self::len()];
91 let len = buf.len().min(other.len());
92 buf[..len].clone_from_slice(&other[..len]);
93 Self::new_from_array(buf)
94 }
95 pub fn new_from_array(buf: [u8; 8usize]) -> Self {
96 unsafe { std::mem::transmute(buf) }
97 }
98 pub fn as_slice(&self) -> &[u8] {
99 unsafe {
100 let ptr: *const u8 = std::mem::transmute(self as *const Self);
101 std::slice::from_raw_parts(ptr, Self::len())
102 }
103 }
104 pub fn from_slice(buf: &[u8]) -> &Self {
105 assert!(buf.len() >= Self::len());
106 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
107 unsafe { std::mem::transmute(buf.as_ptr()) }
108 }
109 pub fn as_array(&self) -> &[u8; 8usize] {
110 unsafe { std::mem::transmute(self) }
111 }
112 pub fn from_array(buf: &[u8; 8usize]) -> &Self {
113 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
114 unsafe { std::mem::transmute(buf) }
115 }
116 pub fn into_array(self) -> [u8; 8usize] {
117 unsafe { std::mem::transmute(self) }
118 }
119 pub const fn len() -> usize {
120 const _: () = assert!(std::mem::size_of::<Ifaddrmsg>() == 8usize);
121 8usize
122 }
123}
124impl std::fmt::Debug for Ifaddrmsg {
125 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 fmt.debug_struct("Ifaddrmsg")
127 .field("ifa_family", &self.ifa_family)
128 .field("ifa_prefixlen", &self.ifa_prefixlen)
129 .field(
130 "ifa_flags",
131 &FormatFlags(self.ifa_flags.into(), IfaFlags::from_value),
132 )
133 .field("ifa_scope", &self.ifa_scope)
134 .field("ifa_index", &self.ifa_index)
135 .finish()
136 }
137}
138#[derive(Debug)]
139#[repr(C, packed(4))]
140pub struct IfaCacheinfo {
141 pub ifa_prefered: u32,
142 pub ifa_valid: u32,
143 pub cstamp: u32,
144 pub tstamp: u32,
145}
146impl Clone for IfaCacheinfo {
147 fn clone(&self) -> Self {
148 Self::new_from_array(*self.as_array())
149 }
150}
151#[doc = "Create zero-initialized struct"]
152impl Default for IfaCacheinfo {
153 fn default() -> Self {
154 Self::new()
155 }
156}
157impl IfaCacheinfo {
158 #[doc = "Create zero-initialized struct"]
159 pub fn new() -> Self {
160 Self::new_from_array([0u8; Self::len()])
161 }
162 #[doc = "Copy from contents from slice"]
163 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
164 if other.len() != Self::len() {
165 return None;
166 }
167 let mut buf = [0u8; Self::len()];
168 buf.clone_from_slice(other);
169 Some(Self::new_from_array(buf))
170 }
171 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
172 pub fn new_from_zeroed(other: &[u8]) -> Self {
173 let mut buf = [0u8; Self::len()];
174 let len = buf.len().min(other.len());
175 buf[..len].clone_from_slice(&other[..len]);
176 Self::new_from_array(buf)
177 }
178 pub fn new_from_array(buf: [u8; 16usize]) -> Self {
179 unsafe { std::mem::transmute(buf) }
180 }
181 pub fn as_slice(&self) -> &[u8] {
182 unsafe {
183 let ptr: *const u8 = std::mem::transmute(self as *const Self);
184 std::slice::from_raw_parts(ptr, Self::len())
185 }
186 }
187 pub fn from_slice(buf: &[u8]) -> &Self {
188 assert!(buf.len() >= Self::len());
189 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
190 unsafe { std::mem::transmute(buf.as_ptr()) }
191 }
192 pub fn as_array(&self) -> &[u8; 16usize] {
193 unsafe { std::mem::transmute(self) }
194 }
195 pub fn from_array(buf: &[u8; 16usize]) -> &Self {
196 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
197 unsafe { std::mem::transmute(buf) }
198 }
199 pub fn into_array(self) -> [u8; 16usize] {
200 unsafe { std::mem::transmute(self) }
201 }
202 pub const fn len() -> usize {
203 const _: () = assert!(std::mem::size_of::<IfaCacheinfo>() == 16usize);
204 16usize
205 }
206}
207#[derive(Clone)]
208pub enum AddrAttrs<'a> {
209 Address(std::net::IpAddr),
210 Local(std::net::IpAddr),
211 Label(&'a CStr),
212 Broadcast(std::net::Ipv4Addr),
213 Anycast(&'a [u8]),
214 Cacheinfo(IfaCacheinfo),
215 Multicast(&'a [u8]),
216 #[doc = "Associated type: [`IfaFlags`] (1 bit per enumeration)"]
217 Flags(u32),
218 RtPriority(u32),
219 TargetNetnsid(&'a [u8]),
220 Proto(u8),
221}
222impl<'a> IterableAddrAttrs<'a> {
223 pub fn get_address(&self) -> Result<std::net::IpAddr, ErrorContext> {
224 let mut iter = self.clone();
225 iter.pos = 0;
226 for attr in iter {
227 if let AddrAttrs::Address(val) = attr? {
228 return Ok(val);
229 }
230 }
231 Err(ErrorContext::new_missing(
232 "AddrAttrs",
233 "Address",
234 self.orig_loc,
235 self.buf.as_ptr() as usize,
236 ))
237 }
238 pub fn get_local(&self) -> Result<std::net::IpAddr, ErrorContext> {
239 let mut iter = self.clone();
240 iter.pos = 0;
241 for attr in iter {
242 if let AddrAttrs::Local(val) = attr? {
243 return Ok(val);
244 }
245 }
246 Err(ErrorContext::new_missing(
247 "AddrAttrs",
248 "Local",
249 self.orig_loc,
250 self.buf.as_ptr() as usize,
251 ))
252 }
253 pub fn get_label(&self) -> Result<&'a CStr, ErrorContext> {
254 let mut iter = self.clone();
255 iter.pos = 0;
256 for attr in iter {
257 if let AddrAttrs::Label(val) = attr? {
258 return Ok(val);
259 }
260 }
261 Err(ErrorContext::new_missing(
262 "AddrAttrs",
263 "Label",
264 self.orig_loc,
265 self.buf.as_ptr() as usize,
266 ))
267 }
268 pub fn get_broadcast(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
269 let mut iter = self.clone();
270 iter.pos = 0;
271 for attr in iter {
272 if let AddrAttrs::Broadcast(val) = attr? {
273 return Ok(val);
274 }
275 }
276 Err(ErrorContext::new_missing(
277 "AddrAttrs",
278 "Broadcast",
279 self.orig_loc,
280 self.buf.as_ptr() as usize,
281 ))
282 }
283 pub fn get_anycast(&self) -> Result<&'a [u8], ErrorContext> {
284 let mut iter = self.clone();
285 iter.pos = 0;
286 for attr in iter {
287 if let AddrAttrs::Anycast(val) = attr? {
288 return Ok(val);
289 }
290 }
291 Err(ErrorContext::new_missing(
292 "AddrAttrs",
293 "Anycast",
294 self.orig_loc,
295 self.buf.as_ptr() as usize,
296 ))
297 }
298 pub fn get_cacheinfo(&self) -> Result<IfaCacheinfo, ErrorContext> {
299 let mut iter = self.clone();
300 iter.pos = 0;
301 for attr in iter {
302 if let AddrAttrs::Cacheinfo(val) = attr? {
303 return Ok(val);
304 }
305 }
306 Err(ErrorContext::new_missing(
307 "AddrAttrs",
308 "Cacheinfo",
309 self.orig_loc,
310 self.buf.as_ptr() as usize,
311 ))
312 }
313 pub fn get_multicast(&self) -> Result<&'a [u8], ErrorContext> {
314 let mut iter = self.clone();
315 iter.pos = 0;
316 for attr in iter {
317 if let AddrAttrs::Multicast(val) = attr? {
318 return Ok(val);
319 }
320 }
321 Err(ErrorContext::new_missing(
322 "AddrAttrs",
323 "Multicast",
324 self.orig_loc,
325 self.buf.as_ptr() as usize,
326 ))
327 }
328 #[doc = "Associated type: [`IfaFlags`] (1 bit per enumeration)"]
329 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
330 let mut iter = self.clone();
331 iter.pos = 0;
332 for attr in iter {
333 if let AddrAttrs::Flags(val) = attr? {
334 return Ok(val);
335 }
336 }
337 Err(ErrorContext::new_missing(
338 "AddrAttrs",
339 "Flags",
340 self.orig_loc,
341 self.buf.as_ptr() as usize,
342 ))
343 }
344 pub fn get_rt_priority(&self) -> Result<u32, ErrorContext> {
345 let mut iter = self.clone();
346 iter.pos = 0;
347 for attr in iter {
348 if let AddrAttrs::RtPriority(val) = attr? {
349 return Ok(val);
350 }
351 }
352 Err(ErrorContext::new_missing(
353 "AddrAttrs",
354 "RtPriority",
355 self.orig_loc,
356 self.buf.as_ptr() as usize,
357 ))
358 }
359 pub fn get_target_netnsid(&self) -> Result<&'a [u8], ErrorContext> {
360 let mut iter = self.clone();
361 iter.pos = 0;
362 for attr in iter {
363 if let AddrAttrs::TargetNetnsid(val) = attr? {
364 return Ok(val);
365 }
366 }
367 Err(ErrorContext::new_missing(
368 "AddrAttrs",
369 "TargetNetnsid",
370 self.orig_loc,
371 self.buf.as_ptr() as usize,
372 ))
373 }
374 pub fn get_proto(&self) -> Result<u8, ErrorContext> {
375 let mut iter = self.clone();
376 iter.pos = 0;
377 for attr in iter {
378 if let AddrAttrs::Proto(val) = attr? {
379 return Ok(val);
380 }
381 }
382 Err(ErrorContext::new_missing(
383 "AddrAttrs",
384 "Proto",
385 self.orig_loc,
386 self.buf.as_ptr() as usize,
387 ))
388 }
389}
390impl AddrAttrs<'_> {
391 pub fn new<'a>(buf: &'a [u8]) -> IterableAddrAttrs<'a> {
392 IterableAddrAttrs::with_loc(buf, buf.as_ptr() as usize)
393 }
394 fn attr_from_type(r#type: u16) -> Option<&'static str> {
395 let res = match r#type {
396 1u16 => "Address",
397 2u16 => "Local",
398 3u16 => "Label",
399 4u16 => "Broadcast",
400 5u16 => "Anycast",
401 6u16 => "Cacheinfo",
402 7u16 => "Multicast",
403 8u16 => "Flags",
404 9u16 => "RtPriority",
405 10u16 => "TargetNetnsid",
406 11u16 => "Proto",
407 _ => return None,
408 };
409 Some(res)
410 }
411}
412#[derive(Clone, Copy, Default)]
413pub struct IterableAddrAttrs<'a> {
414 buf: &'a [u8],
415 pos: usize,
416 orig_loc: usize,
417}
418impl<'a> IterableAddrAttrs<'a> {
419 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
420 Self {
421 buf,
422 pos: 0,
423 orig_loc,
424 }
425 }
426 pub fn get_buf(&self) -> &'a [u8] {
427 self.buf
428 }
429}
430impl<'a> Iterator for IterableAddrAttrs<'a> {
431 type Item = Result<AddrAttrs<'a>, ErrorContext>;
432 fn next(&mut self) -> Option<Self::Item> {
433 let pos = self.pos;
434 let mut r#type;
435 loop {
436 r#type = None;
437 if self.buf.len() == self.pos {
438 return None;
439 }
440 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
441 break;
442 };
443 r#type = Some(header.r#type);
444 let res = match header.r#type {
445 1u16 => AddrAttrs::Address({
446 let res = parse_ip(next);
447 let Some(val) = res else { break };
448 val
449 }),
450 2u16 => AddrAttrs::Local({
451 let res = parse_ip(next);
452 let Some(val) = res else { break };
453 val
454 }),
455 3u16 => AddrAttrs::Label({
456 let res = CStr::from_bytes_with_nul(next).ok();
457 let Some(val) = res else { break };
458 val
459 }),
460 4u16 => AddrAttrs::Broadcast({
461 let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
462 let Some(val) = res else { break };
463 val
464 }),
465 5u16 => AddrAttrs::Anycast({
466 let res = Some(next);
467 let Some(val) = res else { break };
468 val
469 }),
470 6u16 => AddrAttrs::Cacheinfo({
471 let res = Some(IfaCacheinfo::new_from_zeroed(next));
472 let Some(val) = res else { break };
473 val
474 }),
475 7u16 => AddrAttrs::Multicast({
476 let res = Some(next);
477 let Some(val) = res else { break };
478 val
479 }),
480 8u16 => AddrAttrs::Flags({
481 let res = parse_u32(next);
482 let Some(val) = res else { break };
483 val
484 }),
485 9u16 => AddrAttrs::RtPriority({
486 let res = parse_u32(next);
487 let Some(val) = res else { break };
488 val
489 }),
490 10u16 => AddrAttrs::TargetNetnsid({
491 let res = Some(next);
492 let Some(val) = res else { break };
493 val
494 }),
495 11u16 => AddrAttrs::Proto({
496 let res = parse_u8(next);
497 let Some(val) = res else { break };
498 val
499 }),
500 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
501 n => continue,
502 };
503 return Some(Ok(res));
504 }
505 Some(Err(ErrorContext::new(
506 "AddrAttrs",
507 r#type.and_then(|t| AddrAttrs::attr_from_type(t)),
508 self.orig_loc,
509 self.buf.as_ptr().wrapping_add(pos) as usize,
510 )))
511 }
512}
513impl<'a> std::fmt::Debug for IterableAddrAttrs<'_> {
514 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
515 let mut fmt = f.debug_struct("AddrAttrs");
516 for attr in self.clone() {
517 let attr = match attr {
518 Ok(a) => a,
519 Err(err) => {
520 fmt.finish()?;
521 f.write_str("Err(")?;
522 err.fmt(f)?;
523 return f.write_str(")");
524 }
525 };
526 match attr {
527 AddrAttrs::Address(val) => fmt.field("Address", &val),
528 AddrAttrs::Local(val) => fmt.field("Local", &val),
529 AddrAttrs::Label(val) => fmt.field("Label", &val),
530 AddrAttrs::Broadcast(val) => fmt.field("Broadcast", &val),
531 AddrAttrs::Anycast(val) => fmt.field("Anycast", &val),
532 AddrAttrs::Cacheinfo(val) => fmt.field("Cacheinfo", &val),
533 AddrAttrs::Multicast(val) => fmt.field("Multicast", &val),
534 AddrAttrs::Flags(val) => {
535 fmt.field("Flags", &FormatFlags(val.into(), IfaFlags::from_value))
536 }
537 AddrAttrs::RtPriority(val) => fmt.field("RtPriority", &val),
538 AddrAttrs::TargetNetnsid(val) => fmt.field("TargetNetnsid", &val),
539 AddrAttrs::Proto(val) => fmt.field("Proto", &val),
540 };
541 }
542 fmt.finish()
543 }
544}
545impl IterableAddrAttrs<'_> {
546 pub fn lookup_attr(
547 &self,
548 offset: usize,
549 missing_type: Option<u16>,
550 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
551 let mut stack = Vec::new();
552 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
553 if missing_type.is_some() && cur == offset {
554 stack.push(("AddrAttrs", offset));
555 return (
556 stack,
557 missing_type.and_then(|t| AddrAttrs::attr_from_type(t)),
558 );
559 }
560 if cur > offset || cur + self.buf.len() < offset {
561 return (stack, None);
562 }
563 let mut attrs = self.clone();
564 let mut last_off = cur + attrs.pos;
565 while let Some(attr) = attrs.next() {
566 let Ok(attr) = attr else { break };
567 match attr {
568 AddrAttrs::Address(val) => {
569 if last_off == offset {
570 stack.push(("Address", last_off));
571 break;
572 }
573 }
574 AddrAttrs::Local(val) => {
575 if last_off == offset {
576 stack.push(("Local", last_off));
577 break;
578 }
579 }
580 AddrAttrs::Label(val) => {
581 if last_off == offset {
582 stack.push(("Label", last_off));
583 break;
584 }
585 }
586 AddrAttrs::Broadcast(val) => {
587 if last_off == offset {
588 stack.push(("Broadcast", last_off));
589 break;
590 }
591 }
592 AddrAttrs::Anycast(val) => {
593 if last_off == offset {
594 stack.push(("Anycast", last_off));
595 break;
596 }
597 }
598 AddrAttrs::Cacheinfo(val) => {
599 if last_off == offset {
600 stack.push(("Cacheinfo", last_off));
601 break;
602 }
603 }
604 AddrAttrs::Multicast(val) => {
605 if last_off == offset {
606 stack.push(("Multicast", last_off));
607 break;
608 }
609 }
610 AddrAttrs::Flags(val) => {
611 if last_off == offset {
612 stack.push(("Flags", last_off));
613 break;
614 }
615 }
616 AddrAttrs::RtPriority(val) => {
617 if last_off == offset {
618 stack.push(("RtPriority", last_off));
619 break;
620 }
621 }
622 AddrAttrs::TargetNetnsid(val) => {
623 if last_off == offset {
624 stack.push(("TargetNetnsid", last_off));
625 break;
626 }
627 }
628 AddrAttrs::Proto(val) => {
629 if last_off == offset {
630 stack.push(("Proto", last_off));
631 break;
632 }
633 }
634 _ => {}
635 };
636 last_off = cur + attrs.pos;
637 }
638 if !stack.is_empty() {
639 stack.push(("AddrAttrs", cur));
640 }
641 (stack, None)
642 }
643}
644pub struct PushAddrAttrs<Prev: Rec> {
645 pub(crate) prev: Option<Prev>,
646 pub(crate) header_offset: Option<usize>,
647}
648impl<Prev: Rec> Rec for PushAddrAttrs<Prev> {
649 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
650 self.prev.as_mut().unwrap().as_rec_mut()
651 }
652 fn as_rec(&self) -> &Vec<u8> {
653 self.prev.as_ref().unwrap().as_rec()
654 }
655}
656impl<Prev: Rec> PushAddrAttrs<Prev> {
657 pub fn new(prev: Prev) -> Self {
658 Self {
659 prev: Some(prev),
660 header_offset: None,
661 }
662 }
663 pub fn end_nested(mut self) -> Prev {
664 let mut prev = self.prev.take().unwrap();
665 if let Some(header_offset) = &self.header_offset {
666 finalize_nested_header(prev.as_rec_mut(), *header_offset);
667 }
668 prev
669 }
670 pub fn push_address(mut self, value: std::net::IpAddr) -> Self {
671 push_header(self.as_rec_mut(), 1u16, {
672 match &value {
673 IpAddr::V4(_) => 4,
674 IpAddr::V6(_) => 16,
675 }
676 } as u16);
677 encode_ip(self.as_rec_mut(), value);
678 self
679 }
680 pub fn push_local(mut self, value: std::net::IpAddr) -> Self {
681 push_header(self.as_rec_mut(), 2u16, {
682 match &value {
683 IpAddr::V4(_) => 4,
684 IpAddr::V6(_) => 16,
685 }
686 } as u16);
687 encode_ip(self.as_rec_mut(), value);
688 self
689 }
690 pub fn push_label(mut self, value: &CStr) -> Self {
691 push_header(
692 self.as_rec_mut(),
693 3u16,
694 value.to_bytes_with_nul().len() as u16,
695 );
696 self.as_rec_mut().extend(value.to_bytes_with_nul());
697 self
698 }
699 pub fn push_label_bytes(mut self, value: &[u8]) -> Self {
700 push_header(self.as_rec_mut(), 3u16, (value.len() + 1) as u16);
701 self.as_rec_mut().extend(value);
702 self.as_rec_mut().push(0);
703 self
704 }
705 pub fn push_broadcast(mut self, value: std::net::Ipv4Addr) -> Self {
706 push_header(self.as_rec_mut(), 4u16, 4 as u16);
707 self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
708 self
709 }
710 pub fn push_anycast(mut self, value: &[u8]) -> Self {
711 push_header(self.as_rec_mut(), 5u16, value.len() as u16);
712 self.as_rec_mut().extend(value);
713 self
714 }
715 pub fn push_cacheinfo(mut self, value: IfaCacheinfo) -> Self {
716 push_header(self.as_rec_mut(), 6u16, value.as_slice().len() as u16);
717 self.as_rec_mut().extend(value.as_slice());
718 self
719 }
720 pub fn push_multicast(mut self, value: &[u8]) -> Self {
721 push_header(self.as_rec_mut(), 7u16, value.len() as u16);
722 self.as_rec_mut().extend(value);
723 self
724 }
725 #[doc = "Associated type: [`IfaFlags`] (1 bit per enumeration)"]
726 pub fn push_flags(mut self, value: u32) -> Self {
727 push_header(self.as_rec_mut(), 8u16, 4 as u16);
728 self.as_rec_mut().extend(value.to_ne_bytes());
729 self
730 }
731 pub fn push_rt_priority(mut self, value: u32) -> Self {
732 push_header(self.as_rec_mut(), 9u16, 4 as u16);
733 self.as_rec_mut().extend(value.to_ne_bytes());
734 self
735 }
736 pub fn push_target_netnsid(mut self, value: &[u8]) -> Self {
737 push_header(self.as_rec_mut(), 10u16, value.len() as u16);
738 self.as_rec_mut().extend(value);
739 self
740 }
741 pub fn push_proto(mut self, value: u8) -> Self {
742 push_header(self.as_rec_mut(), 11u16, 1 as u16);
743 self.as_rec_mut().extend(value.to_ne_bytes());
744 self
745 }
746}
747impl<Prev: Rec> Drop for PushAddrAttrs<Prev> {
748 fn drop(&mut self) {
749 if let Some(prev) = &mut self.prev {
750 if let Some(header_offset) = &self.header_offset {
751 finalize_nested_header(prev.as_rec_mut(), *header_offset);
752 }
753 }
754 }
755}
756#[doc = "Add new address\nRequest attributes:\n- [.push_address()](PushAddrAttrs::push_address)\n- [.push_local()](PushAddrAttrs::push_local)\n- [.push_label()](PushAddrAttrs::push_label)\n- [.push_cacheinfo()](PushAddrAttrs::push_cacheinfo)\n"]
757#[derive(Debug)]
758pub struct OpNewaddrDo<'r> {
759 request: Request<'r>,
760}
761impl<'r> OpNewaddrDo<'r> {
762 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
763 Self::write_header(request.buf_mut(), header);
764 Self { request: request }
765 }
766 pub fn encode_request<'buf>(
767 buf: &'buf mut Vec<u8>,
768 header: &Ifaddrmsg,
769 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
770 Self::write_header(buf, header);
771 PushAddrAttrs::new(buf)
772 }
773 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
774 PushAddrAttrs::new(self.request.buf_mut())
775 }
776 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
777 PushAddrAttrs::new(self.request.buf)
778 }
779 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
780 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
781 (
782 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
783 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
784 )
785 }
786 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
787 prev.as_rec_mut().extend(header.as_slice());
788 }
789}
790impl NetlinkRequest for OpNewaddrDo<'_> {
791 fn protocol(&self) -> Protocol {
792 Protocol::Raw {
793 protonum: 0u16,
794 request_type: 20u16,
795 }
796 }
797 fn flags(&self) -> u16 {
798 self.request.flags
799 }
800 fn payload(&self) -> &[u8] {
801 self.request.buf()
802 }
803 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
804 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
805 Self::decode_request(buf)
806 }
807 fn lookup(
808 buf: &[u8],
809 offset: usize,
810 missing_type: Option<u16>,
811 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
812 Self::decode_request(buf)
813 .1
814 .lookup_attr(offset, missing_type)
815 }
816}
817#[doc = "Remove address\nRequest attributes:\n- [.push_address()](PushAddrAttrs::push_address)\n- [.push_local()](PushAddrAttrs::push_local)\n"]
818#[derive(Debug)]
819pub struct OpDeladdrDo<'r> {
820 request: Request<'r>,
821}
822impl<'r> OpDeladdrDo<'r> {
823 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
824 Self::write_header(request.buf_mut(), header);
825 Self { request: request }
826 }
827 pub fn encode_request<'buf>(
828 buf: &'buf mut Vec<u8>,
829 header: &Ifaddrmsg,
830 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
831 Self::write_header(buf, header);
832 PushAddrAttrs::new(buf)
833 }
834 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
835 PushAddrAttrs::new(self.request.buf_mut())
836 }
837 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
838 PushAddrAttrs::new(self.request.buf)
839 }
840 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
841 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
842 (
843 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
844 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
845 )
846 }
847 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
848 prev.as_rec_mut().extend(header.as_slice());
849 }
850}
851impl NetlinkRequest for OpDeladdrDo<'_> {
852 fn protocol(&self) -> Protocol {
853 Protocol::Raw {
854 protonum: 0u16,
855 request_type: 21u16,
856 }
857 }
858 fn flags(&self) -> u16 {
859 self.request.flags
860 }
861 fn payload(&self) -> &[u8] {
862 self.request.buf()
863 }
864 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
865 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
866 Self::decode_request(buf)
867 }
868 fn lookup(
869 buf: &[u8],
870 offset: usize,
871 missing_type: Option<u16>,
872 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
873 Self::decode_request(buf)
874 .1
875 .lookup_attr(offset, missing_type)
876 }
877}
878#[doc = "Dump address information\\.\n\nReply attributes:\n- [.get_address()](IterableAddrAttrs::get_address)\n- [.get_local()](IterableAddrAttrs::get_local)\n- [.get_label()](IterableAddrAttrs::get_label)\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n"]
879#[derive(Debug)]
880pub struct OpGetaddrDump<'r> {
881 request: Request<'r>,
882}
883impl<'r> OpGetaddrDump<'r> {
884 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
885 Self::write_header(request.buf_mut(), header);
886 Self {
887 request: request.set_dump(),
888 }
889 }
890 pub fn encode_request<'buf>(
891 buf: &'buf mut Vec<u8>,
892 header: &Ifaddrmsg,
893 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
894 Self::write_header(buf, header);
895 PushAddrAttrs::new(buf)
896 }
897 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
898 PushAddrAttrs::new(self.request.buf_mut())
899 }
900 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
901 PushAddrAttrs::new(self.request.buf)
902 }
903 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
904 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
905 (
906 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
907 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
908 )
909 }
910 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
911 prev.as_rec_mut().extend(header.as_slice());
912 }
913}
914impl NetlinkRequest for OpGetaddrDump<'_> {
915 fn protocol(&self) -> Protocol {
916 Protocol::Raw {
917 protonum: 0u16,
918 request_type: 22u16,
919 }
920 }
921 fn flags(&self) -> u16 {
922 self.request.flags
923 }
924 fn payload(&self) -> &[u8] {
925 self.request.buf()
926 }
927 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
928 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
929 Self::decode_request(buf)
930 }
931 fn lookup(
932 buf: &[u8],
933 offset: usize,
934 missing_type: Option<u16>,
935 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
936 Self::decode_request(buf)
937 .1
938 .lookup_attr(offset, missing_type)
939 }
940}
941#[doc = "Get / dump IPv4/IPv6 multicast addresses\\.\n\nReply attributes:\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n- [.get_multicast()](IterableAddrAttrs::get_multicast)\n"]
942#[derive(Debug)]
943pub struct OpGetmulticastDump<'r> {
944 request: Request<'r>,
945}
946impl<'r> OpGetmulticastDump<'r> {
947 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
948 Self::write_header(request.buf_mut(), header);
949 Self {
950 request: request.set_dump(),
951 }
952 }
953 pub fn encode_request<'buf>(
954 buf: &'buf mut Vec<u8>,
955 header: &Ifaddrmsg,
956 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
957 Self::write_header(buf, header);
958 PushAddrAttrs::new(buf)
959 }
960 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
961 PushAddrAttrs::new(self.request.buf_mut())
962 }
963 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
964 PushAddrAttrs::new(self.request.buf)
965 }
966 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
967 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
968 (
969 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
970 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
971 )
972 }
973 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
974 prev.as_rec_mut().extend(header.as_slice());
975 }
976}
977impl NetlinkRequest for OpGetmulticastDump<'_> {
978 fn protocol(&self) -> Protocol {
979 Protocol::Raw {
980 protonum: 0u16,
981 request_type: 58u16,
982 }
983 }
984 fn flags(&self) -> u16 {
985 self.request.flags
986 }
987 fn payload(&self) -> &[u8] {
988 self.request.buf()
989 }
990 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
991 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
992 Self::decode_request(buf)
993 }
994 fn lookup(
995 buf: &[u8],
996 offset: usize,
997 missing_type: Option<u16>,
998 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
999 Self::decode_request(buf)
1000 .1
1001 .lookup_attr(offset, missing_type)
1002 }
1003}
1004#[doc = "Get / dump IPv4/IPv6 multicast addresses\\.\n\nReply attributes:\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n- [.get_multicast()](IterableAddrAttrs::get_multicast)\n"]
1005#[derive(Debug)]
1006pub struct OpGetmulticastDo<'r> {
1007 request: Request<'r>,
1008}
1009impl<'r> OpGetmulticastDo<'r> {
1010 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
1011 Self::write_header(request.buf_mut(), header);
1012 Self { request: request }
1013 }
1014 pub fn encode_request<'buf>(
1015 buf: &'buf mut Vec<u8>,
1016 header: &Ifaddrmsg,
1017 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
1018 Self::write_header(buf, header);
1019 PushAddrAttrs::new(buf)
1020 }
1021 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
1022 PushAddrAttrs::new(self.request.buf_mut())
1023 }
1024 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
1025 PushAddrAttrs::new(self.request.buf)
1026 }
1027 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
1028 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
1029 (
1030 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
1031 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
1032 )
1033 }
1034 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
1035 prev.as_rec_mut().extend(header.as_slice());
1036 }
1037}
1038impl NetlinkRequest for OpGetmulticastDo<'_> {
1039 fn protocol(&self) -> Protocol {
1040 Protocol::Raw {
1041 protonum: 0u16,
1042 request_type: 58u16,
1043 }
1044 }
1045 fn flags(&self) -> u16 {
1046 self.request.flags
1047 }
1048 fn payload(&self) -> &[u8] {
1049 self.request.buf()
1050 }
1051 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
1052 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1053 Self::decode_request(buf)
1054 }
1055 fn lookup(
1056 buf: &[u8],
1057 offset: usize,
1058 missing_type: Option<u16>,
1059 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1060 Self::decode_request(buf)
1061 .1
1062 .lookup_attr(offset, missing_type)
1063 }
1064}
1065#[derive(Debug)]
1066pub struct ChainedFinal<'a> {
1067 inner: Chained<'a>,
1068}
1069#[derive(Debug)]
1070pub struct Chained<'a> {
1071 buf: RequestBuf<'a>,
1072 first_seq: u32,
1073 lookups: Vec<(&'static str, LookupFn)>,
1074 last_header_offset: usize,
1075 last_kind: Option<RequestInfo>,
1076}
1077impl<'a> ChainedFinal<'a> {
1078 pub fn into_chained(self) -> Chained<'a> {
1079 self.inner
1080 }
1081 pub fn buf(&self) -> &Vec<u8> {
1082 self.inner.buf()
1083 }
1084 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1085 self.inner.buf_mut()
1086 }
1087 fn get_index(&self, seq: u32) -> Option<u32> {
1088 let min = self.inner.first_seq;
1089 let max = min.wrapping_add(self.inner.lookups.len() as u32);
1090 return if min <= max {
1091 (min..max).contains(&seq).then(|| seq - min)
1092 } else if min <= seq {
1093 Some(seq - min)
1094 } else if seq < max {
1095 Some(u32::MAX - min + seq)
1096 } else {
1097 None
1098 };
1099 }
1100}
1101impl crate::traits::NetlinkChained for ChainedFinal<'_> {
1102 fn protonum(&self) -> u16 {
1103 PROTONUM
1104 }
1105 fn payload(&self) -> &[u8] {
1106 self.buf()
1107 }
1108 fn chain_len(&self) -> usize {
1109 self.inner.lookups.len()
1110 }
1111 fn get_index(&self, seq: u32) -> Option<usize> {
1112 self.get_index(seq).map(|n| n as usize)
1113 }
1114 fn name(&self, index: usize) -> &'static str {
1115 self.inner.lookups[index].0
1116 }
1117 fn lookup(&self, index: usize) -> LookupFn {
1118 self.inner.lookups[index].1
1119 }
1120}
1121impl Chained<'static> {
1122 pub fn new(first_seq: u32) -> Self {
1123 Self::new_from_buf(Vec::new(), first_seq)
1124 }
1125 pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
1126 Self {
1127 buf: RequestBuf::Own(buf),
1128 first_seq,
1129 lookups: Vec::new(),
1130 last_header_offset: 0,
1131 last_kind: None,
1132 }
1133 }
1134 pub fn into_buf(self) -> Vec<u8> {
1135 match self.buf {
1136 RequestBuf::Own(buf) => buf,
1137 _ => unreachable!(),
1138 }
1139 }
1140}
1141impl<'a> Chained<'a> {
1142 pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
1143 Self {
1144 buf: RequestBuf::Ref(buf),
1145 first_seq,
1146 lookups: Vec::new(),
1147 last_header_offset: 0,
1148 last_kind: None,
1149 }
1150 }
1151 pub fn finalize(mut self) -> ChainedFinal<'a> {
1152 self.update_header();
1153 ChainedFinal { inner: self }
1154 }
1155 pub fn request(&mut self) -> Request<'_> {
1156 self.update_header();
1157 self.last_header_offset = self.buf().len();
1158 self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
1159 let mut request = Request::new_extend(self.buf.buf_mut());
1160 self.last_kind = None;
1161 request.writeback = Some(&mut self.last_kind);
1162 request
1163 }
1164 pub fn buf(&self) -> &Vec<u8> {
1165 self.buf.buf()
1166 }
1167 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1168 self.buf.buf_mut()
1169 }
1170 fn update_header(&mut self) {
1171 let Some(RequestInfo {
1172 protocol,
1173 flags,
1174 name,
1175 lookup,
1176 }) = self.last_kind
1177 else {
1178 if !self.buf().is_empty() {
1179 assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
1180 self.buf.buf_mut().truncate(self.last_header_offset);
1181 }
1182 return;
1183 };
1184 let header_offset = self.last_header_offset;
1185 let request_type = match protocol {
1186 Protocol::Raw { request_type, .. } => request_type,
1187 Protocol::Generic(_) => unreachable!(),
1188 };
1189 let index = self.lookups.len();
1190 let seq = self.first_seq.wrapping_add(index as u32);
1191 self.lookups.push((name, lookup));
1192 let buf = self.buf_mut();
1193 align(buf);
1194 let header = Nlmsghdr {
1195 len: (buf.len() - header_offset) as u32,
1196 r#type: request_type,
1197 flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
1198 seq,
1199 pid: 0,
1200 };
1201 buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
1202 }
1203}
1204use crate::traits::LookupFn;
1205use crate::utils::RequestBuf;
1206#[derive(Debug)]
1207pub struct Request<'buf> {
1208 buf: RequestBuf<'buf>,
1209 flags: u16,
1210 writeback: Option<&'buf mut Option<RequestInfo>>,
1211}
1212#[allow(unused)]
1213#[derive(Debug, Clone)]
1214pub struct RequestInfo {
1215 protocol: Protocol,
1216 flags: u16,
1217 name: &'static str,
1218 lookup: LookupFn,
1219}
1220impl Request<'static> {
1221 pub fn new() -> Self {
1222 Self::new_from_buf(Vec::new())
1223 }
1224 pub fn new_from_buf(buf: Vec<u8>) -> Self {
1225 Self {
1226 flags: 0,
1227 buf: RequestBuf::Own(buf),
1228 writeback: None,
1229 }
1230 }
1231 pub fn into_buf(self) -> Vec<u8> {
1232 match self.buf {
1233 RequestBuf::Own(buf) => buf,
1234 _ => unreachable!(),
1235 }
1236 }
1237}
1238impl<'buf> Request<'buf> {
1239 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1240 buf.clear();
1241 Self::new_extend(buf)
1242 }
1243 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1244 Self {
1245 flags: 0,
1246 buf: RequestBuf::Ref(buf),
1247 writeback: None,
1248 }
1249 }
1250 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1251 let Some(writeback) = &mut self.writeback else {
1252 return;
1253 };
1254 **writeback = Some(RequestInfo {
1255 protocol,
1256 flags: self.flags,
1257 name,
1258 lookup,
1259 })
1260 }
1261 pub fn buf(&self) -> &Vec<u8> {
1262 self.buf.buf()
1263 }
1264 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1265 self.buf.buf_mut()
1266 }
1267 #[doc = "Set `NLM_F_CREATE` flag"]
1268 pub fn set_create(mut self) -> Self {
1269 self.flags |= consts::NLM_F_CREATE as u16;
1270 self
1271 }
1272 #[doc = "Set `NLM_F_EXCL` flag"]
1273 pub fn set_excl(mut self) -> Self {
1274 self.flags |= consts::NLM_F_EXCL as u16;
1275 self
1276 }
1277 #[doc = "Set `NLM_F_REPLACE` flag"]
1278 pub fn set_replace(mut self) -> Self {
1279 self.flags |= consts::NLM_F_REPLACE as u16;
1280 self
1281 }
1282 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1283 pub fn set_change(self) -> Self {
1284 self.set_create().set_replace()
1285 }
1286 #[doc = "Set `NLM_F_APPEND` flag"]
1287 pub fn set_append(mut self) -> Self {
1288 self.flags |= consts::NLM_F_APPEND as u16;
1289 self
1290 }
1291 #[doc = "Set `self.flags |= flags`"]
1292 pub fn set_flags(mut self, flags: u16) -> Self {
1293 self.flags |= flags;
1294 self
1295 }
1296 #[doc = "Set `self.flags ^= self.flags & flags`"]
1297 pub fn unset_flags(mut self, flags: u16) -> Self {
1298 self.flags ^= self.flags & flags;
1299 self
1300 }
1301 #[doc = "Set `NLM_F_DUMP` flag"]
1302 fn set_dump(mut self) -> Self {
1303 self.flags |= consts::NLM_F_DUMP as u16;
1304 self
1305 }
1306 #[doc = "Add new address\nRequest attributes:\n- [.push_address()](PushAddrAttrs::push_address)\n- [.push_local()](PushAddrAttrs::push_local)\n- [.push_label()](PushAddrAttrs::push_label)\n- [.push_cacheinfo()](PushAddrAttrs::push_cacheinfo)\n"]
1307 pub fn op_newaddr_do(self, header: &Ifaddrmsg) -> OpNewaddrDo<'buf> {
1308 let mut res = OpNewaddrDo::new(self, header);
1309 res.request
1310 .do_writeback(res.protocol(), "op-newaddr-do", OpNewaddrDo::lookup);
1311 res
1312 }
1313 #[doc = "Remove address\nRequest attributes:\n- [.push_address()](PushAddrAttrs::push_address)\n- [.push_local()](PushAddrAttrs::push_local)\n"]
1314 pub fn op_deladdr_do(self, header: &Ifaddrmsg) -> OpDeladdrDo<'buf> {
1315 let mut res = OpDeladdrDo::new(self, header);
1316 res.request
1317 .do_writeback(res.protocol(), "op-deladdr-do", OpDeladdrDo::lookup);
1318 res
1319 }
1320 #[doc = "Dump address information\\.\n\nReply attributes:\n- [.get_address()](IterableAddrAttrs::get_address)\n- [.get_local()](IterableAddrAttrs::get_local)\n- [.get_label()](IterableAddrAttrs::get_label)\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n"]
1321 pub fn op_getaddr_dump(self, header: &Ifaddrmsg) -> OpGetaddrDump<'buf> {
1322 let mut res = OpGetaddrDump::new(self, header);
1323 res.request
1324 .do_writeback(res.protocol(), "op-getaddr-dump", OpGetaddrDump::lookup);
1325 res
1326 }
1327 #[doc = "Get / dump IPv4/IPv6 multicast addresses\\.\n\nReply attributes:\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n- [.get_multicast()](IterableAddrAttrs::get_multicast)\n"]
1328 pub fn op_getmulticast_dump(self, header: &Ifaddrmsg) -> OpGetmulticastDump<'buf> {
1329 let mut res = OpGetmulticastDump::new(self, header);
1330 res.request.do_writeback(
1331 res.protocol(),
1332 "op-getmulticast-dump",
1333 OpGetmulticastDump::lookup,
1334 );
1335 res
1336 }
1337 #[doc = "Get / dump IPv4/IPv6 multicast addresses\\.\n\nReply attributes:\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n- [.get_multicast()](IterableAddrAttrs::get_multicast)\n"]
1338 pub fn op_getmulticast_do(self, header: &Ifaddrmsg) -> OpGetmulticastDo<'buf> {
1339 let mut res = OpGetmulticastDo::new(self, header);
1340 res.request.do_writeback(
1341 res.protocol(),
1342 "op-getmulticast-do",
1343 OpGetmulticastDo::lookup,
1344 );
1345 res
1346 }
1347}
1348#[cfg(test)]
1349mod generated_tests {
1350 use super::*;
1351 #[test]
1352 fn tests() {
1353 let _ = IterableAddrAttrs::get_address;
1354 let _ = IterableAddrAttrs::get_cacheinfo;
1355 let _ = IterableAddrAttrs::get_label;
1356 let _ = IterableAddrAttrs::get_local;
1357 let _ = IterableAddrAttrs::get_multicast;
1358 let _ = PushAddrAttrs::<&mut Vec<u8>>::push_address;
1359 let _ = PushAddrAttrs::<&mut Vec<u8>>::push_cacheinfo;
1360 let _ = PushAddrAttrs::<&mut Vec<u8>>::push_label;
1361 let _ = PushAddrAttrs::<&mut Vec<u8>>::push_local;
1362 }
1363}