1#![doc = "Address configuration over rtnetlink.\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &str = "rt-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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 Ok(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 mut pos;
434 let mut r#type;
435 loop {
436 pos = self.pos;
437 r#type = None;
438 if self.buf.len() == self.pos {
439 return None;
440 }
441 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
442 self.pos = self.buf.len();
443 break;
444 };
445 r#type = Some(header.r#type);
446 let res = match header.r#type {
447 1u16 => AddrAttrs::Address({
448 let res = parse_ip(next);
449 let Some(val) = res else { break };
450 val
451 }),
452 2u16 => AddrAttrs::Local({
453 let res = parse_ip(next);
454 let Some(val) = res else { break };
455 val
456 }),
457 3u16 => AddrAttrs::Label({
458 let res = CStr::from_bytes_with_nul(next).ok();
459 let Some(val) = res else { break };
460 val
461 }),
462 4u16 => AddrAttrs::Broadcast({
463 let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
464 let Some(val) = res else { break };
465 val
466 }),
467 5u16 => AddrAttrs::Anycast({
468 let res = Some(next);
469 let Some(val) = res else { break };
470 val
471 }),
472 6u16 => AddrAttrs::Cacheinfo({
473 let res = Some(IfaCacheinfo::new_from_zeroed(next));
474 let Some(val) = res else { break };
475 val
476 }),
477 7u16 => AddrAttrs::Multicast({
478 let res = Some(next);
479 let Some(val) = res else { break };
480 val
481 }),
482 8u16 => AddrAttrs::Flags({
483 let res = parse_u32(next);
484 let Some(val) = res else { break };
485 val
486 }),
487 9u16 => AddrAttrs::RtPriority({
488 let res = parse_u32(next);
489 let Some(val) = res else { break };
490 val
491 }),
492 10u16 => AddrAttrs::TargetNetnsid({
493 let res = Some(next);
494 let Some(val) = res else { break };
495 val
496 }),
497 11u16 => AddrAttrs::Proto({
498 let res = parse_u8(next);
499 let Some(val) = res else { break };
500 val
501 }),
502 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
503 n => continue,
504 };
505 return Some(Ok(res));
506 }
507 Some(Err(ErrorContext::new(
508 "AddrAttrs",
509 r#type.and_then(|t| AddrAttrs::attr_from_type(t)),
510 self.orig_loc,
511 self.buf.as_ptr().wrapping_add(pos) as usize,
512 )))
513 }
514}
515impl<'a> std::fmt::Debug for IterableAddrAttrs<'_> {
516 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
517 let mut fmt = f.debug_struct("AddrAttrs");
518 for attr in self.clone() {
519 let attr = match attr {
520 Ok(a) => a,
521 Err(err) => {
522 fmt.finish()?;
523 f.write_str("Err(")?;
524 err.fmt(f)?;
525 return f.write_str(")");
526 }
527 };
528 match attr {
529 AddrAttrs::Address(val) => fmt.field("Address", &val),
530 AddrAttrs::Local(val) => fmt.field("Local", &val),
531 AddrAttrs::Label(val) => fmt.field("Label", &val),
532 AddrAttrs::Broadcast(val) => fmt.field("Broadcast", &val),
533 AddrAttrs::Anycast(val) => fmt.field("Anycast", &val),
534 AddrAttrs::Cacheinfo(val) => fmt.field("Cacheinfo", &val),
535 AddrAttrs::Multicast(val) => fmt.field("Multicast", &val),
536 AddrAttrs::Flags(val) => {
537 fmt.field("Flags", &FormatFlags(val.into(), IfaFlags::from_value))
538 }
539 AddrAttrs::RtPriority(val) => fmt.field("RtPriority", &val),
540 AddrAttrs::TargetNetnsid(val) => fmt.field("TargetNetnsid", &val),
541 AddrAttrs::Proto(val) => fmt.field("Proto", &val),
542 };
543 }
544 fmt.finish()
545 }
546}
547impl IterableAddrAttrs<'_> {
548 pub fn lookup_attr(
549 &self,
550 offset: usize,
551 missing_type: Option<u16>,
552 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
553 let mut stack = Vec::new();
554 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
555 if missing_type.is_some() && cur == offset {
556 stack.push(("AddrAttrs", offset));
557 return (
558 stack,
559 missing_type.and_then(|t| AddrAttrs::attr_from_type(t)),
560 );
561 }
562 if cur > offset || cur + self.buf.len() < offset {
563 return (stack, None);
564 }
565 let mut attrs = self.clone();
566 let mut last_off = cur + attrs.pos;
567 while let Some(attr) = attrs.next() {
568 let Ok(attr) = attr else { break };
569 match attr {
570 AddrAttrs::Address(val) => {
571 if last_off == offset {
572 stack.push(("Address", last_off));
573 break;
574 }
575 }
576 AddrAttrs::Local(val) => {
577 if last_off == offset {
578 stack.push(("Local", last_off));
579 break;
580 }
581 }
582 AddrAttrs::Label(val) => {
583 if last_off == offset {
584 stack.push(("Label", last_off));
585 break;
586 }
587 }
588 AddrAttrs::Broadcast(val) => {
589 if last_off == offset {
590 stack.push(("Broadcast", last_off));
591 break;
592 }
593 }
594 AddrAttrs::Anycast(val) => {
595 if last_off == offset {
596 stack.push(("Anycast", last_off));
597 break;
598 }
599 }
600 AddrAttrs::Cacheinfo(val) => {
601 if last_off == offset {
602 stack.push(("Cacheinfo", last_off));
603 break;
604 }
605 }
606 AddrAttrs::Multicast(val) => {
607 if last_off == offset {
608 stack.push(("Multicast", last_off));
609 break;
610 }
611 }
612 AddrAttrs::Flags(val) => {
613 if last_off == offset {
614 stack.push(("Flags", last_off));
615 break;
616 }
617 }
618 AddrAttrs::RtPriority(val) => {
619 if last_off == offset {
620 stack.push(("RtPriority", last_off));
621 break;
622 }
623 }
624 AddrAttrs::TargetNetnsid(val) => {
625 if last_off == offset {
626 stack.push(("TargetNetnsid", last_off));
627 break;
628 }
629 }
630 AddrAttrs::Proto(val) => {
631 if last_off == offset {
632 stack.push(("Proto", last_off));
633 break;
634 }
635 }
636 _ => {}
637 };
638 last_off = cur + attrs.pos;
639 }
640 if !stack.is_empty() {
641 stack.push(("AddrAttrs", cur));
642 }
643 (stack, None)
644 }
645}
646pub struct PushAddrAttrs<Prev: Pusher> {
647 pub(crate) prev: Option<Prev>,
648 pub(crate) header_offset: Option<usize>,
649}
650impl<Prev: Pusher> Pusher for PushAddrAttrs<Prev> {
651 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
652 self.prev.as_mut().unwrap().as_vec_mut()
653 }
654 fn as_vec(&self) -> &Vec<u8> {
655 self.prev.as_ref().unwrap().as_vec()
656 }
657}
658impl<Prev: Pusher> PushAddrAttrs<Prev> {
659 pub fn new(prev: Prev) -> Self {
660 Self {
661 prev: Some(prev),
662 header_offset: None,
663 }
664 }
665 pub fn end_nested(mut self) -> Prev {
666 let mut prev = self.prev.take().unwrap();
667 if let Some(header_offset) = &self.header_offset {
668 finalize_nested_header(prev.as_vec_mut(), *header_offset);
669 }
670 prev
671 }
672 pub fn push_address(mut self, value: std::net::IpAddr) -> Self {
673 push_header(self.as_vec_mut(), 1u16, {
674 match &value {
675 IpAddr::V4(_) => 4,
676 IpAddr::V6(_) => 16,
677 }
678 } as u16);
679 encode_ip(self.as_vec_mut(), value);
680 self
681 }
682 pub fn push_local(mut self, value: std::net::IpAddr) -> Self {
683 push_header(self.as_vec_mut(), 2u16, {
684 match &value {
685 IpAddr::V4(_) => 4,
686 IpAddr::V6(_) => 16,
687 }
688 } as u16);
689 encode_ip(self.as_vec_mut(), value);
690 self
691 }
692 pub fn push_label(mut self, value: &CStr) -> Self {
693 push_header(
694 self.as_vec_mut(),
695 3u16,
696 value.to_bytes_with_nul().len() as u16,
697 );
698 self.as_vec_mut().extend(value.to_bytes_with_nul());
699 self
700 }
701 pub fn push_label_bytes(mut self, value: &[u8]) -> Self {
702 push_header(self.as_vec_mut(), 3u16, (value.len() + 1) as u16);
703 self.as_vec_mut().extend(value);
704 self.as_vec_mut().push(0);
705 self
706 }
707 pub fn push_broadcast(mut self, value: std::net::Ipv4Addr) -> Self {
708 push_header(self.as_vec_mut(), 4u16, 4 as u16);
709 self.as_vec_mut().extend(&value.to_bits().to_be_bytes());
710 self
711 }
712 pub fn push_anycast(mut self, value: &[u8]) -> Self {
713 push_header(self.as_vec_mut(), 5u16, value.len() as u16);
714 self.as_vec_mut().extend(value);
715 self
716 }
717 pub fn push_cacheinfo(mut self, value: IfaCacheinfo) -> Self {
718 push_header(self.as_vec_mut(), 6u16, value.as_slice().len() as u16);
719 self.as_vec_mut().extend(value.as_slice());
720 self
721 }
722 pub fn push_multicast(mut self, value: &[u8]) -> Self {
723 push_header(self.as_vec_mut(), 7u16, value.len() as u16);
724 self.as_vec_mut().extend(value);
725 self
726 }
727 #[doc = "Associated type: [`IfaFlags`] (1 bit per enumeration)"]
728 pub fn push_flags(mut self, value: u32) -> Self {
729 push_header(self.as_vec_mut(), 8u16, 4 as u16);
730 self.as_vec_mut().extend(value.to_ne_bytes());
731 self
732 }
733 pub fn push_rt_priority(mut self, value: u32) -> Self {
734 push_header(self.as_vec_mut(), 9u16, 4 as u16);
735 self.as_vec_mut().extend(value.to_ne_bytes());
736 self
737 }
738 pub fn push_target_netnsid(mut self, value: &[u8]) -> Self {
739 push_header(self.as_vec_mut(), 10u16, value.len() as u16);
740 self.as_vec_mut().extend(value);
741 self
742 }
743 pub fn push_proto(mut self, value: u8) -> Self {
744 push_header(self.as_vec_mut(), 11u16, 1 as u16);
745 self.as_vec_mut().extend(value.to_ne_bytes());
746 self
747 }
748}
749impl<Prev: Pusher> Drop for PushAddrAttrs<Prev> {
750 fn drop(&mut self) {
751 if let Some(prev) = &mut self.prev {
752 if let Some(header_offset) = &self.header_offset {
753 finalize_nested_header(prev.as_vec_mut(), *header_offset);
754 }
755 }
756 }
757}
758#[doc = "Add new address\n\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\n"]
759#[derive(Debug)]
760pub struct OpNewaddrDo<'r> {
761 request: Request<'r>,
762}
763impl<'r> OpNewaddrDo<'r> {
764 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
765 Self::write_header(request.buf_mut(), header);
766 Self { request: request }
767 }
768 pub fn encode_request<'buf>(
769 buf: &'buf mut Vec<u8>,
770 header: &Ifaddrmsg,
771 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
772 Self::write_header(buf, header);
773 PushAddrAttrs::new(buf)
774 }
775 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
776 PushAddrAttrs::new(self.request.buf_mut())
777 }
778 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
779 PushAddrAttrs::new(self.request.buf)
780 }
781 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
782 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
783 (
784 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
785 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
786 )
787 }
788 fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ifaddrmsg) {
789 prev.as_vec_mut().extend(header.as_slice());
790 }
791}
792impl NetlinkRequest for OpNewaddrDo<'_> {
793 fn protocol(&self) -> Protocol {
794 Protocol::Raw {
795 protonum: 0u16,
796 request_type: 20u16,
797 }
798 }
799 fn flags(&self) -> u16 {
800 self.request.flags
801 }
802 fn payload(&self) -> &[u8] {
803 self.request.buf()
804 }
805 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
806 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
807 Self::decode_request(buf)
808 }
809 fn lookup(
810 buf: &[u8],
811 offset: usize,
812 missing_type: Option<u16>,
813 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
814 Self::decode_request(buf)
815 .1
816 .lookup_attr(offset, missing_type)
817 }
818}
819#[doc = "Remove address\n\nRequest attributes:\n- [.push_address()](PushAddrAttrs::push_address)\n- [.push_local()](PushAddrAttrs::push_local)\n\n"]
820#[derive(Debug)]
821pub struct OpDeladdrDo<'r> {
822 request: Request<'r>,
823}
824impl<'r> OpDeladdrDo<'r> {
825 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
826 Self::write_header(request.buf_mut(), header);
827 Self { request: request }
828 }
829 pub fn encode_request<'buf>(
830 buf: &'buf mut Vec<u8>,
831 header: &Ifaddrmsg,
832 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
833 Self::write_header(buf, header);
834 PushAddrAttrs::new(buf)
835 }
836 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
837 PushAddrAttrs::new(self.request.buf_mut())
838 }
839 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
840 PushAddrAttrs::new(self.request.buf)
841 }
842 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
843 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
844 (
845 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
846 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
847 )
848 }
849 fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ifaddrmsg) {
850 prev.as_vec_mut().extend(header.as_slice());
851 }
852}
853impl NetlinkRequest for OpDeladdrDo<'_> {
854 fn protocol(&self) -> Protocol {
855 Protocol::Raw {
856 protonum: 0u16,
857 request_type: 21u16,
858 }
859 }
860 fn flags(&self) -> u16 {
861 self.request.flags
862 }
863 fn payload(&self) -> &[u8] {
864 self.request.buf()
865 }
866 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
867 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
868 Self::decode_request(buf)
869 }
870 fn lookup(
871 buf: &[u8],
872 offset: usize,
873 missing_type: Option<u16>,
874 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
875 Self::decode_request(buf)
876 .1
877 .lookup_attr(offset, missing_type)
878 }
879}
880#[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\n"]
881#[derive(Debug)]
882pub struct OpGetaddrDump<'r> {
883 request: Request<'r>,
884}
885impl<'r> OpGetaddrDump<'r> {
886 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
887 Self::write_header(request.buf_mut(), header);
888 Self {
889 request: request.set_dump(),
890 }
891 }
892 pub fn encode_request<'buf>(
893 buf: &'buf mut Vec<u8>,
894 header: &Ifaddrmsg,
895 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
896 Self::write_header(buf, header);
897 PushAddrAttrs::new(buf)
898 }
899 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
900 PushAddrAttrs::new(self.request.buf_mut())
901 }
902 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
903 PushAddrAttrs::new(self.request.buf)
904 }
905 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
906 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
907 (
908 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
909 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
910 )
911 }
912 fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ifaddrmsg) {
913 prev.as_vec_mut().extend(header.as_slice());
914 }
915}
916impl NetlinkRequest for OpGetaddrDump<'_> {
917 fn protocol(&self) -> Protocol {
918 Protocol::Raw {
919 protonum: 0u16,
920 request_type: 22u16,
921 }
922 }
923 fn flags(&self) -> u16 {
924 self.request.flags
925 }
926 fn payload(&self) -> &[u8] {
927 self.request.buf()
928 }
929 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
930 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
931 Self::decode_request(buf)
932 }
933 fn lookup(
934 buf: &[u8],
935 offset: usize,
936 missing_type: Option<u16>,
937 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
938 Self::decode_request(buf)
939 .1
940 .lookup_attr(offset, missing_type)
941 }
942}
943#[doc = "Get / dump IPv4/IPv6 multicast addresses.\n\nReply attributes:\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n- [.get_multicast()](IterableAddrAttrs::get_multicast)\n\n"]
944#[derive(Debug)]
945pub struct OpGetmulticastDump<'r> {
946 request: Request<'r>,
947}
948impl<'r> OpGetmulticastDump<'r> {
949 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
950 Self::write_header(request.buf_mut(), header);
951 Self {
952 request: request.set_dump(),
953 }
954 }
955 pub fn encode_request<'buf>(
956 buf: &'buf mut Vec<u8>,
957 header: &Ifaddrmsg,
958 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
959 Self::write_header(buf, header);
960 PushAddrAttrs::new(buf)
961 }
962 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
963 PushAddrAttrs::new(self.request.buf_mut())
964 }
965 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
966 PushAddrAttrs::new(self.request.buf)
967 }
968 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
969 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
970 (
971 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
972 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
973 )
974 }
975 fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ifaddrmsg) {
976 prev.as_vec_mut().extend(header.as_slice());
977 }
978}
979impl NetlinkRequest for OpGetmulticastDump<'_> {
980 fn protocol(&self) -> Protocol {
981 Protocol::Raw {
982 protonum: 0u16,
983 request_type: 58u16,
984 }
985 }
986 fn flags(&self) -> u16 {
987 self.request.flags
988 }
989 fn payload(&self) -> &[u8] {
990 self.request.buf()
991 }
992 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
993 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
994 Self::decode_request(buf)
995 }
996 fn lookup(
997 buf: &[u8],
998 offset: usize,
999 missing_type: Option<u16>,
1000 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1001 Self::decode_request(buf)
1002 .1
1003 .lookup_attr(offset, missing_type)
1004 }
1005}
1006#[doc = "Get / dump IPv4/IPv6 multicast addresses.\n\nReply attributes:\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n- [.get_multicast()](IterableAddrAttrs::get_multicast)\n\n"]
1007#[derive(Debug)]
1008pub struct OpGetmulticastDo<'r> {
1009 request: Request<'r>,
1010}
1011impl<'r> OpGetmulticastDo<'r> {
1012 pub fn new(mut request: Request<'r>, header: &Ifaddrmsg) -> Self {
1013 Self::write_header(request.buf_mut(), header);
1014 Self { request: request }
1015 }
1016 pub fn encode_request<'buf>(
1017 buf: &'buf mut Vec<u8>,
1018 header: &Ifaddrmsg,
1019 ) -> PushAddrAttrs<&'buf mut Vec<u8>> {
1020 Self::write_header(buf, header);
1021 PushAddrAttrs::new(buf)
1022 }
1023 pub fn encode(&mut self) -> PushAddrAttrs<&mut Vec<u8>> {
1024 PushAddrAttrs::new(self.request.buf_mut())
1025 }
1026 pub fn into_encoder(self) -> PushAddrAttrs<RequestBuf<'r>> {
1027 PushAddrAttrs::new(self.request.buf)
1028 }
1029 pub fn decode_request<'a>(buf: &'a [u8]) -> (Ifaddrmsg, IterableAddrAttrs<'a>) {
1030 let (header, attrs) = buf.split_at(buf.len().min(Ifaddrmsg::len()));
1031 (
1032 Ifaddrmsg::new_from_slice(header).unwrap_or_default(),
1033 IterableAddrAttrs::with_loc(attrs, buf.as_ptr() as usize),
1034 )
1035 }
1036 fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Ifaddrmsg) {
1037 prev.as_vec_mut().extend(header.as_slice());
1038 }
1039}
1040impl NetlinkRequest for OpGetmulticastDo<'_> {
1041 fn protocol(&self) -> Protocol {
1042 Protocol::Raw {
1043 protonum: 0u16,
1044 request_type: 58u16,
1045 }
1046 }
1047 fn flags(&self) -> u16 {
1048 self.request.flags
1049 }
1050 fn payload(&self) -> &[u8] {
1051 self.request.buf()
1052 }
1053 type ReplyType<'buf> = (Ifaddrmsg, IterableAddrAttrs<'buf>);
1054 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1055 Self::decode_request(buf)
1056 }
1057 fn lookup(
1058 buf: &[u8],
1059 offset: usize,
1060 missing_type: Option<u16>,
1061 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1062 Self::decode_request(buf)
1063 .1
1064 .lookup_attr(offset, missing_type)
1065 }
1066}
1067#[derive(Debug)]
1068pub struct ChainedFinal<'a> {
1069 inner: Chained<'a>,
1070}
1071#[derive(Debug)]
1072pub struct Chained<'a> {
1073 buf: RequestBuf<'a>,
1074 first_seq: u32,
1075 lookups: Vec<(&'static str, LookupFn)>,
1076 last_header_offset: usize,
1077 last_kind: Option<RequestInfo>,
1078}
1079impl<'a> ChainedFinal<'a> {
1080 pub fn into_chained(self) -> Chained<'a> {
1081 self.inner
1082 }
1083 pub fn buf(&self) -> &Vec<u8> {
1084 self.inner.buf()
1085 }
1086 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1087 self.inner.buf_mut()
1088 }
1089 fn get_index(&self, seq: u32) -> Option<u32> {
1090 let min = self.inner.first_seq;
1091 let max = min.wrapping_add(self.inner.lookups.len() as u32);
1092 return if min <= max {
1093 (min..max).contains(&seq).then(|| seq - min)
1094 } else if min <= seq {
1095 Some(seq - min)
1096 } else if seq < max {
1097 Some(u32::MAX - min + seq)
1098 } else {
1099 None
1100 };
1101 }
1102}
1103impl crate::traits::NetlinkChained for ChainedFinal<'_> {
1104 fn protonum(&self) -> u16 {
1105 PROTONUM
1106 }
1107 fn payload(&self) -> &[u8] {
1108 self.buf()
1109 }
1110 fn chain_len(&self) -> usize {
1111 self.inner.lookups.len()
1112 }
1113 fn get_index(&self, seq: u32) -> Option<usize> {
1114 self.get_index(seq).map(|n| n as usize)
1115 }
1116 fn name(&self, index: usize) -> &'static str {
1117 self.inner.lookups[index].0
1118 }
1119 fn lookup(&self, index: usize) -> LookupFn {
1120 self.inner.lookups[index].1
1121 }
1122}
1123impl Chained<'static> {
1124 pub fn new(first_seq: u32) -> Self {
1125 Self::new_from_buf(Vec::new(), first_seq)
1126 }
1127 pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
1128 Self {
1129 buf: RequestBuf::Own(buf),
1130 first_seq,
1131 lookups: Vec::new(),
1132 last_header_offset: 0,
1133 last_kind: None,
1134 }
1135 }
1136 pub fn into_buf(self) -> Vec<u8> {
1137 match self.buf {
1138 RequestBuf::Own(buf) => buf,
1139 _ => unreachable!(),
1140 }
1141 }
1142}
1143impl<'a> Chained<'a> {
1144 pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
1145 Self {
1146 buf: RequestBuf::Ref(buf),
1147 first_seq,
1148 lookups: Vec::new(),
1149 last_header_offset: 0,
1150 last_kind: None,
1151 }
1152 }
1153 pub fn finalize(mut self) -> ChainedFinal<'a> {
1154 self.update_header();
1155 ChainedFinal { inner: self }
1156 }
1157 pub fn request(&mut self) -> Request<'_> {
1158 self.update_header();
1159 self.last_header_offset = self.buf().len();
1160 self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
1161 let mut request = Request::new_extend(self.buf.buf_mut());
1162 self.last_kind = None;
1163 request.writeback = Some(&mut self.last_kind);
1164 request
1165 }
1166 pub fn buf(&self) -> &Vec<u8> {
1167 self.buf.buf()
1168 }
1169 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1170 self.buf.buf_mut()
1171 }
1172 fn update_header(&mut self) {
1173 let Some(RequestInfo {
1174 protocol,
1175 flags,
1176 name,
1177 lookup,
1178 }) = self.last_kind
1179 else {
1180 if !self.buf().is_empty() {
1181 assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
1182 self.buf.buf_mut().truncate(self.last_header_offset);
1183 }
1184 return;
1185 };
1186 let header_offset = self.last_header_offset;
1187 let request_type = match protocol {
1188 Protocol::Raw { request_type, .. } => request_type,
1189 Protocol::Generic(_) => unreachable!(),
1190 };
1191 let index = self.lookups.len();
1192 let seq = self.first_seq.wrapping_add(index as u32);
1193 self.lookups.push((name, lookup));
1194 let buf = self.buf_mut();
1195 align(buf);
1196 let header = Nlmsghdr {
1197 len: (buf.len() - header_offset) as u32,
1198 r#type: request_type,
1199 flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
1200 seq,
1201 pid: 0,
1202 };
1203 buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
1204 }
1205}
1206use crate::traits::LookupFn;
1207use crate::utils::RequestBuf;
1208#[derive(Debug)]
1209pub struct Request<'buf> {
1210 buf: RequestBuf<'buf>,
1211 flags: u16,
1212 writeback: Option<&'buf mut Option<RequestInfo>>,
1213}
1214#[allow(unused)]
1215#[derive(Debug, Clone)]
1216pub struct RequestInfo {
1217 protocol: Protocol,
1218 flags: u16,
1219 name: &'static str,
1220 lookup: LookupFn,
1221}
1222impl Request<'static> {
1223 pub fn new() -> Self {
1224 Self::new_from_buf(Vec::new())
1225 }
1226 pub fn new_from_buf(buf: Vec<u8>) -> Self {
1227 Self {
1228 flags: 0,
1229 buf: RequestBuf::Own(buf),
1230 writeback: None,
1231 }
1232 }
1233 pub fn into_buf(self) -> Vec<u8> {
1234 match self.buf {
1235 RequestBuf::Own(buf) => buf,
1236 _ => unreachable!(),
1237 }
1238 }
1239}
1240impl<'buf> Request<'buf> {
1241 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1242 buf.clear();
1243 Self::new_extend(buf)
1244 }
1245 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1246 Self {
1247 flags: 0,
1248 buf: RequestBuf::Ref(buf),
1249 writeback: None,
1250 }
1251 }
1252 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1253 let Some(writeback) = &mut self.writeback else {
1254 return;
1255 };
1256 **writeback = Some(RequestInfo {
1257 protocol,
1258 flags: self.flags,
1259 name,
1260 lookup,
1261 })
1262 }
1263 pub fn buf(&self) -> &Vec<u8> {
1264 self.buf.buf()
1265 }
1266 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1267 self.buf.buf_mut()
1268 }
1269 #[doc = "Set `NLM_F_CREATE` flag"]
1270 pub fn set_create(mut self) -> Self {
1271 self.flags |= consts::NLM_F_CREATE as u16;
1272 self
1273 }
1274 #[doc = "Set `NLM_F_EXCL` flag"]
1275 pub fn set_excl(mut self) -> Self {
1276 self.flags |= consts::NLM_F_EXCL as u16;
1277 self
1278 }
1279 #[doc = "Set `NLM_F_REPLACE` flag"]
1280 pub fn set_replace(mut self) -> Self {
1281 self.flags |= consts::NLM_F_REPLACE as u16;
1282 self
1283 }
1284 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1285 pub fn set_change(self) -> Self {
1286 self.set_create().set_replace()
1287 }
1288 #[doc = "Set `NLM_F_APPEND` flag"]
1289 pub fn set_append(mut self) -> Self {
1290 self.flags |= consts::NLM_F_APPEND as u16;
1291 self
1292 }
1293 #[doc = "Set `self.flags |= flags`"]
1294 pub fn set_flags(mut self, flags: u16) -> Self {
1295 self.flags |= flags;
1296 self
1297 }
1298 #[doc = "Set `self.flags ^= self.flags & flags`"]
1299 pub fn unset_flags(mut self, flags: u16) -> Self {
1300 self.flags ^= self.flags & flags;
1301 self
1302 }
1303 #[doc = "Set `NLM_F_DUMP` flag"]
1304 fn set_dump(mut self) -> Self {
1305 self.flags |= consts::NLM_F_DUMP as u16;
1306 self
1307 }
1308 #[doc = "Add new address\n\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\n"]
1309 pub fn op_newaddr_do(self, header: &Ifaddrmsg) -> OpNewaddrDo<'buf> {
1310 let mut res = OpNewaddrDo::new(self, header);
1311 res.request
1312 .do_writeback(res.protocol(), "op-newaddr-do", OpNewaddrDo::lookup);
1313 res
1314 }
1315 #[doc = "Remove address\n\nRequest attributes:\n- [.push_address()](PushAddrAttrs::push_address)\n- [.push_local()](PushAddrAttrs::push_local)\n\n"]
1316 pub fn op_deladdr_do(self, header: &Ifaddrmsg) -> OpDeladdrDo<'buf> {
1317 let mut res = OpDeladdrDo::new(self, header);
1318 res.request
1319 .do_writeback(res.protocol(), "op-deladdr-do", OpDeladdrDo::lookup);
1320 res
1321 }
1322 #[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\n"]
1323 pub fn op_getaddr_dump(self, header: &Ifaddrmsg) -> OpGetaddrDump<'buf> {
1324 let mut res = OpGetaddrDump::new(self, header);
1325 res.request
1326 .do_writeback(res.protocol(), "op-getaddr-dump", OpGetaddrDump::lookup);
1327 res
1328 }
1329 #[doc = "Get / dump IPv4/IPv6 multicast addresses.\n\nReply attributes:\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n- [.get_multicast()](IterableAddrAttrs::get_multicast)\n\n"]
1330 pub fn op_getmulticast_dump(self, header: &Ifaddrmsg) -> OpGetmulticastDump<'buf> {
1331 let mut res = OpGetmulticastDump::new(self, header);
1332 res.request.do_writeback(
1333 res.protocol(),
1334 "op-getmulticast-dump",
1335 OpGetmulticastDump::lookup,
1336 );
1337 res
1338 }
1339 #[doc = "Get / dump IPv4/IPv6 multicast addresses.\n\nReply attributes:\n- [.get_cacheinfo()](IterableAddrAttrs::get_cacheinfo)\n- [.get_multicast()](IterableAddrAttrs::get_multicast)\n\n"]
1340 pub fn op_getmulticast_do(self, header: &Ifaddrmsg) -> OpGetmulticastDo<'buf> {
1341 let mut res = OpGetmulticastDo::new(self, header);
1342 res.request.do_writeback(
1343 res.protocol(),
1344 "op-getmulticast-do",
1345 OpGetmulticastDo::lookup,
1346 );
1347 res
1348 }
1349}
1350#[cfg(test)]
1351mod generated_tests {
1352 use super::*;
1353 #[test]
1354 fn tests() {
1355 let _ = IterableAddrAttrs::get_address;
1356 let _ = IterableAddrAttrs::get_cacheinfo;
1357 let _ = IterableAddrAttrs::get_label;
1358 let _ = IterableAddrAttrs::get_local;
1359 let _ = IterableAddrAttrs::get_multicast;
1360 let _ = PushAddrAttrs::<&mut Vec<u8>>::push_address;
1361 let _ = PushAddrAttrs::<&mut Vec<u8>>::push_cacheinfo;
1362 let _ = PushAddrAttrs::<&mut Vec<u8>>::push_label;
1363 let _ = PushAddrAttrs::<&mut Vec<u8>>::push_local;
1364 }
1365}