Skip to main content

netlink_bindings/rt-addr/
mod.rs

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}