Skip to main content

netlink_bindings/rt-addr/
mod.rs

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: Rec> {
647    pub(crate) prev: Option<Prev>,
648    pub(crate) header_offset: Option<usize>,
649}
650impl<Prev: Rec> Rec for PushAddrAttrs<Prev> {
651    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
652        self.prev.as_mut().unwrap().as_rec_mut()
653    }
654    fn as_rec(&self) -> &Vec<u8> {
655        self.prev.as_ref().unwrap().as_rec()
656    }
657}
658impl<Prev: Rec> 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_rec_mut(), *header_offset);
669        }
670        prev
671    }
672    pub fn push_address(mut self, value: std::net::IpAddr) -> Self {
673        push_header(self.as_rec_mut(), 1u16, {
674            match &value {
675                IpAddr::V4(_) => 4,
676                IpAddr::V6(_) => 16,
677            }
678        } as u16);
679        encode_ip(self.as_rec_mut(), value);
680        self
681    }
682    pub fn push_local(mut self, value: std::net::IpAddr) -> Self {
683        push_header(self.as_rec_mut(), 2u16, {
684            match &value {
685                IpAddr::V4(_) => 4,
686                IpAddr::V6(_) => 16,
687            }
688        } as u16);
689        encode_ip(self.as_rec_mut(), value);
690        self
691    }
692    pub fn push_label(mut self, value: &CStr) -> Self {
693        push_header(
694            self.as_rec_mut(),
695            3u16,
696            value.to_bytes_with_nul().len() as u16,
697        );
698        self.as_rec_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_rec_mut(), 3u16, (value.len() + 1) as u16);
703        self.as_rec_mut().extend(value);
704        self.as_rec_mut().push(0);
705        self
706    }
707    pub fn push_broadcast(mut self, value: std::net::Ipv4Addr) -> Self {
708        push_header(self.as_rec_mut(), 4u16, 4 as u16);
709        self.as_rec_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_rec_mut(), 5u16, value.len() as u16);
714        self.as_rec_mut().extend(value);
715        self
716    }
717    pub fn push_cacheinfo(mut self, value: IfaCacheinfo) -> Self {
718        push_header(self.as_rec_mut(), 6u16, value.as_slice().len() as u16);
719        self.as_rec_mut().extend(value.as_slice());
720        self
721    }
722    pub fn push_multicast(mut self, value: &[u8]) -> Self {
723        push_header(self.as_rec_mut(), 7u16, value.len() as u16);
724        self.as_rec_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_rec_mut(), 8u16, 4 as u16);
730        self.as_rec_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_rec_mut(), 9u16, 4 as u16);
735        self.as_rec_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_rec_mut(), 10u16, value.len() as u16);
740        self.as_rec_mut().extend(value);
741        self
742    }
743    pub fn push_proto(mut self, value: u8) -> Self {
744        push_header(self.as_rec_mut(), 11u16, 1 as u16);
745        self.as_rec_mut().extend(value.to_ne_bytes());
746        self
747    }
748}
749impl<Prev: Rec> 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_rec_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: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
789        prev.as_rec_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: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
850        prev.as_rec_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: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
913        prev.as_rec_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: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
976        prev.as_rec_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: Rec>(prev: &mut Prev, header: &Ifaddrmsg) {
1037        prev.as_rec_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}