Skip to main content

netlink_bindings/wireguard/
mod.rs

1#![doc = "\\*\\*Netlink protocol to control WireGuard network devices\\.\\*\\*\n\nThe below enums and macros are for interfacing with WireGuard, using generic\nnetlink, with family \\`\\`WG\\_GENL\\_NAME\\`\\` and version \\`\\`WG\\_GENL\\_VERSION\\`\\`\\. It\ndefines two commands: get and set\\. Note that while they share many common\nattributes, these two commands actually accept a slightly different set of\ninputs and outputs\\. These differences are noted under the individual\nattributes\\.\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)]
10#[cfg(test)]
11mod tests;
12use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
13use crate::{
14    consts,
15    traits::{NetlinkRequest, Protocol},
16    utils::*,
17};
18pub const PROTONAME: &str = "wireguard";
19pub const PROTONAME_CSTR: &CStr = c"wireguard";
20pub const KEY_LEN: u64 = 32u64;
21#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
22#[derive(Debug, Clone, Copy)]
23pub enum WgdeviceFlags {
24    ReplacePeers = 1 << 0,
25}
26impl WgdeviceFlags {
27    pub fn from_value(value: u64) -> Option<Self> {
28        Some(match value {
29            n if n == 1 << 0 => Self::ReplacePeers,
30            _ => return None,
31        })
32    }
33}
34#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
35#[derive(Debug, Clone, Copy)]
36pub enum WgpeerFlags {
37    RemoveMe = 1 << 0,
38    ReplaceAllowedips = 1 << 1,
39    UpdateOnly = 1 << 2,
40}
41impl WgpeerFlags {
42    pub fn from_value(value: u64) -> Option<Self> {
43        Some(match value {
44            n if n == 1 << 0 => Self::RemoveMe,
45            n if n == 1 << 1 => Self::ReplaceAllowedips,
46            n if n == 1 << 2 => Self::UpdateOnly,
47            _ => return None,
48        })
49    }
50}
51#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
52#[derive(Debug, Clone, Copy)]
53pub enum WgallowedipFlags {
54    RemoveMe = 1 << 0,
55}
56impl WgallowedipFlags {
57    pub fn from_value(value: u64) -> Option<Self> {
58        Some(match value {
59            n if n == 1 << 0 => Self::RemoveMe,
60            _ => return None,
61        })
62    }
63}
64#[repr(C, packed(4))]
65pub struct KernelTimespec {
66    #[doc = "Number of seconds, since UNIX epoch\\."]
67    pub sec: u64,
68    #[doc = "Number of nanoseconds, after the second began\\."]
69    pub nsec: u64,
70}
71impl Clone for KernelTimespec {
72    fn clone(&self) -> Self {
73        Self::new_from_array(*self.as_array())
74    }
75}
76#[doc = "Create zero-initialized struct"]
77impl Default for KernelTimespec {
78    fn default() -> Self {
79        Self::new()
80    }
81}
82impl KernelTimespec {
83    #[doc = "Create zero-initialized struct"]
84    pub fn new() -> Self {
85        Self::new_from_array([0u8; Self::len()])
86    }
87    #[doc = "Copy from contents from slice"]
88    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
89        if other.len() != Self::len() {
90            return None;
91        }
92        let mut buf = [0u8; Self::len()];
93        buf.clone_from_slice(other);
94        Some(Self::new_from_array(buf))
95    }
96    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
97    pub fn new_from_zeroed(other: &[u8]) -> Self {
98        let mut buf = [0u8; Self::len()];
99        let len = buf.len().min(other.len());
100        buf[..len].clone_from_slice(&other[..len]);
101        Self::new_from_array(buf)
102    }
103    pub fn new_from_array(buf: [u8; 16usize]) -> Self {
104        unsafe { std::mem::transmute(buf) }
105    }
106    pub fn as_slice(&self) -> &[u8] {
107        unsafe {
108            let ptr: *const u8 = std::mem::transmute(self as *const Self);
109            std::slice::from_raw_parts(ptr, Self::len())
110        }
111    }
112    pub fn from_slice(buf: &[u8]) -> &Self {
113        assert!(buf.len() >= Self::len());
114        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
115        unsafe { std::mem::transmute(buf.as_ptr()) }
116    }
117    pub fn as_array(&self) -> &[u8; 16usize] {
118        unsafe { std::mem::transmute(self) }
119    }
120    pub fn from_array(buf: &[u8; 16usize]) -> &Self {
121        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
122        unsafe { std::mem::transmute(buf) }
123    }
124    pub fn into_array(self) -> [u8; 16usize] {
125        unsafe { std::mem::transmute(self) }
126    }
127    pub const fn len() -> usize {
128        const _: () = assert!(std::mem::size_of::<KernelTimespec>() == 16usize);
129        16usize
130    }
131}
132impl std::fmt::Debug for KernelTimespec {
133    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134        fmt.debug_struct("KernelTimespec")
135            .field("sec", &{ self.sec })
136            .field("nsec", &{ self.nsec })
137            .finish()
138    }
139}
140#[derive(Clone)]
141pub enum Wgdevice<'a> {
142    Ifindex(u32),
143    Ifname(&'a CStr),
144    #[doc = "Set to all zeros to remove\\."]
145    PrivateKey(&'a [u8]),
146    PublicKey(&'a [u8]),
147    #[doc = "\\`\\`0\\`\\` or \\`\\`WGDEVICE\\_F\\_REPLACE\\_PEERS\\`\\` if all current peers should be\nremoved prior to adding the list below\\.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
148    Flags(u32),
149    #[doc = "Set as \\`\\`0\\`\\` to choose randomly\\."]
150    ListenPort(u16),
151    #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
152    Fwmark(u32),
153    #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
154    Peers(IterableArrayWgpeer<'a>),
155}
156impl<'a> IterableWgdevice<'a> {
157    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
158        let mut iter = self.clone();
159        iter.pos = 0;
160        for attr in iter {
161            if let Wgdevice::Ifindex(val) = attr? {
162                return Ok(val);
163            }
164        }
165        Err(ErrorContext::new_missing(
166            "Wgdevice",
167            "Ifindex",
168            self.orig_loc,
169            self.buf.as_ptr() as usize,
170        ))
171    }
172    pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
173        let mut iter = self.clone();
174        iter.pos = 0;
175        for attr in iter {
176            if let Wgdevice::Ifname(val) = attr? {
177                return Ok(val);
178            }
179        }
180        Err(ErrorContext::new_missing(
181            "Wgdevice",
182            "Ifname",
183            self.orig_loc,
184            self.buf.as_ptr() as usize,
185        ))
186    }
187    #[doc = "Set to all zeros to remove\\."]
188    pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
189        let mut iter = self.clone();
190        iter.pos = 0;
191        for attr in iter {
192            if let Wgdevice::PrivateKey(val) = attr? {
193                return Ok(val);
194            }
195        }
196        Err(ErrorContext::new_missing(
197            "Wgdevice",
198            "PrivateKey",
199            self.orig_loc,
200            self.buf.as_ptr() as usize,
201        ))
202    }
203    pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
204        let mut iter = self.clone();
205        iter.pos = 0;
206        for attr in iter {
207            if let Wgdevice::PublicKey(val) = attr? {
208                return Ok(val);
209            }
210        }
211        Err(ErrorContext::new_missing(
212            "Wgdevice",
213            "PublicKey",
214            self.orig_loc,
215            self.buf.as_ptr() as usize,
216        ))
217    }
218    #[doc = "\\`\\`0\\`\\` or \\`\\`WGDEVICE\\_F\\_REPLACE\\_PEERS\\`\\` if all current peers should be\nremoved prior to adding the list below\\.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
219    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
220        let mut iter = self.clone();
221        iter.pos = 0;
222        for attr in iter {
223            if let Wgdevice::Flags(val) = attr? {
224                return Ok(val);
225            }
226        }
227        Err(ErrorContext::new_missing(
228            "Wgdevice",
229            "Flags",
230            self.orig_loc,
231            self.buf.as_ptr() as usize,
232        ))
233    }
234    #[doc = "Set as \\`\\`0\\`\\` to choose randomly\\."]
235    pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
236        let mut iter = self.clone();
237        iter.pos = 0;
238        for attr in iter {
239            if let Wgdevice::ListenPort(val) = attr? {
240                return Ok(val);
241            }
242        }
243        Err(ErrorContext::new_missing(
244            "Wgdevice",
245            "ListenPort",
246            self.orig_loc,
247            self.buf.as_ptr() as usize,
248        ))
249    }
250    #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
251    pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
252        let mut iter = self.clone();
253        iter.pos = 0;
254        for attr in iter {
255            if let Wgdevice::Fwmark(val) = attr? {
256                return Ok(val);
257            }
258        }
259        Err(ErrorContext::new_missing(
260            "Wgdevice",
261            "Fwmark",
262            self.orig_loc,
263            self.buf.as_ptr() as usize,
264        ))
265    }
266    #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
267    pub fn get_peers(
268        &self,
269    ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
270        for attr in self.clone() {
271            if let Wgdevice::Peers(val) = attr? {
272                return Ok(ArrayIterable::new(val));
273            }
274        }
275        Err(ErrorContext::new_missing(
276            "Wgdevice",
277            "Peers",
278            self.orig_loc,
279            self.buf.as_ptr() as usize,
280        ))
281    }
282}
283impl<'a> Wgpeer<'a> {
284    pub fn new_array(buf: &[u8]) -> IterableArrayWgpeer<'_> {
285        IterableArrayWgpeer::with_loc(buf, buf.as_ptr() as usize)
286    }
287}
288#[derive(Clone, Copy, Default)]
289pub struct IterableArrayWgpeer<'a> {
290    buf: &'a [u8],
291    pos: usize,
292    orig_loc: usize,
293}
294impl<'a> IterableArrayWgpeer<'a> {
295    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
296        Self {
297            buf,
298            pos: 0,
299            orig_loc,
300        }
301    }
302    pub fn get_buf(&self) -> &'a [u8] {
303        self.buf
304    }
305}
306impl<'a> Iterator for IterableArrayWgpeer<'a> {
307    type Item = Result<IterableWgpeer<'a>, ErrorContext>;
308    fn next(&mut self) -> Option<Self::Item> {
309        if self.buf.len() == self.pos {
310            return None;
311        }
312        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
313            {
314                return Some(Ok(IterableWgpeer::with_loc(next, self.orig_loc)));
315            }
316        }
317        Some(Err(ErrorContext::new(
318            "Wgpeer",
319            None,
320            self.orig_loc,
321            self.buf.as_ptr().wrapping_add(self.pos) as usize,
322        )))
323    }
324}
325impl Wgdevice<'_> {
326    pub fn new<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
327        IterableWgdevice::with_loc(buf, buf.as_ptr() as usize)
328    }
329    fn attr_from_type(r#type: u16) -> Option<&'static str> {
330        let res = match r#type {
331            0u16 => "Unspec",
332            1u16 => "Ifindex",
333            2u16 => "Ifname",
334            3u16 => "PrivateKey",
335            4u16 => "PublicKey",
336            5u16 => "Flags",
337            6u16 => "ListenPort",
338            7u16 => "Fwmark",
339            8u16 => "Peers",
340            _ => return None,
341        };
342        Some(res)
343    }
344}
345#[derive(Clone, Copy, Default)]
346pub struct IterableWgdevice<'a> {
347    buf: &'a [u8],
348    pos: usize,
349    orig_loc: usize,
350}
351impl<'a> IterableWgdevice<'a> {
352    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
353        Self {
354            buf,
355            pos: 0,
356            orig_loc,
357        }
358    }
359    pub fn get_buf(&self) -> &'a [u8] {
360        self.buf
361    }
362}
363impl<'a> Iterator for IterableWgdevice<'a> {
364    type Item = Result<Wgdevice<'a>, ErrorContext>;
365    fn next(&mut self) -> Option<Self::Item> {
366        let pos = self.pos;
367        let mut r#type;
368        loop {
369            r#type = None;
370            if self.buf.len() == self.pos {
371                return None;
372            }
373            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
374                break;
375            };
376            r#type = Some(header.r#type);
377            let res = match header.r#type {
378                1u16 => Wgdevice::Ifindex({
379                    let res = parse_u32(next);
380                    let Some(val) = res else { break };
381                    val
382                }),
383                2u16 => Wgdevice::Ifname({
384                    let res = CStr::from_bytes_with_nul(next).ok();
385                    let Some(val) = res else { break };
386                    val
387                }),
388                3u16 => Wgdevice::PrivateKey({
389                    let res = Some(next);
390                    let Some(val) = res else { break };
391                    val
392                }),
393                4u16 => Wgdevice::PublicKey({
394                    let res = Some(next);
395                    let Some(val) = res else { break };
396                    val
397                }),
398                5u16 => Wgdevice::Flags({
399                    let res = parse_u32(next);
400                    let Some(val) = res else { break };
401                    val
402                }),
403                6u16 => Wgdevice::ListenPort({
404                    let res = parse_u16(next);
405                    let Some(val) = res else { break };
406                    val
407                }),
408                7u16 => Wgdevice::Fwmark({
409                    let res = parse_u32(next);
410                    let Some(val) = res else { break };
411                    val
412                }),
413                8u16 => Wgdevice::Peers({
414                    let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
415                    let Some(val) = res else { break };
416                    val
417                }),
418                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
419                n => continue,
420            };
421            return Some(Ok(res));
422        }
423        Some(Err(ErrorContext::new(
424            "Wgdevice",
425            r#type.and_then(|t| Wgdevice::attr_from_type(t)),
426            self.orig_loc,
427            self.buf.as_ptr().wrapping_add(pos) as usize,
428        )))
429    }
430}
431impl std::fmt::Debug for IterableArrayWgpeer<'_> {
432    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
433        fmt.debug_list()
434            .entries(self.clone().map(FlattenErrorContext))
435            .finish()
436    }
437}
438impl<'a> std::fmt::Debug for IterableWgdevice<'_> {
439    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
440        let mut fmt = f.debug_struct("Wgdevice");
441        for attr in self.clone() {
442            let attr = match attr {
443                Ok(a) => a,
444                Err(err) => {
445                    fmt.finish()?;
446                    f.write_str("Err(")?;
447                    err.fmt(f)?;
448                    return f.write_str(")");
449                }
450            };
451            match attr {
452                Wgdevice::Ifindex(val) => fmt.field("Ifindex", &val),
453                Wgdevice::Ifname(val) => fmt.field("Ifname", &val),
454                Wgdevice::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
455                Wgdevice::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
456                Wgdevice::Flags(val) => {
457                    fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
458                }
459                Wgdevice::ListenPort(val) => fmt.field("ListenPort", &val),
460                Wgdevice::Fwmark(val) => fmt.field("Fwmark", &val),
461                Wgdevice::Peers(val) => fmt.field("Peers", &val),
462            };
463        }
464        fmt.finish()
465    }
466}
467impl IterableWgdevice<'_> {
468    pub fn lookup_attr(
469        &self,
470        offset: usize,
471        missing_type: Option<u16>,
472    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
473        let mut stack = Vec::new();
474        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
475        if missing_type.is_some() && cur == offset {
476            stack.push(("Wgdevice", offset));
477            return (
478                stack,
479                missing_type.and_then(|t| Wgdevice::attr_from_type(t)),
480            );
481        }
482        if cur > offset || cur + self.buf.len() < offset {
483            return (stack, None);
484        }
485        let mut attrs = self.clone();
486        let mut last_off = cur + attrs.pos;
487        let mut missing = None;
488        while let Some(attr) = attrs.next() {
489            let Ok(attr) = attr else { break };
490            match attr {
491                Wgdevice::Ifindex(val) => {
492                    if last_off == offset {
493                        stack.push(("Ifindex", last_off));
494                        break;
495                    }
496                }
497                Wgdevice::Ifname(val) => {
498                    if last_off == offset {
499                        stack.push(("Ifname", last_off));
500                        break;
501                    }
502                }
503                Wgdevice::PrivateKey(val) => {
504                    if last_off == offset {
505                        stack.push(("PrivateKey", last_off));
506                        break;
507                    }
508                }
509                Wgdevice::PublicKey(val) => {
510                    if last_off == offset {
511                        stack.push(("PublicKey", last_off));
512                        break;
513                    }
514                }
515                Wgdevice::Flags(val) => {
516                    if last_off == offset {
517                        stack.push(("Flags", last_off));
518                        break;
519                    }
520                }
521                Wgdevice::ListenPort(val) => {
522                    if last_off == offset {
523                        stack.push(("ListenPort", last_off));
524                        break;
525                    }
526                }
527                Wgdevice::Fwmark(val) => {
528                    if last_off == offset {
529                        stack.push(("Fwmark", last_off));
530                        break;
531                    }
532                }
533                Wgdevice::Peers(val) => {
534                    for entry in val {
535                        let Ok(attr) = entry else { break };
536                        (stack, missing) = attr.lookup_attr(offset, missing_type);
537                        if !stack.is_empty() {
538                            break;
539                        }
540                    }
541                    if !stack.is_empty() {
542                        stack.push(("Peers", last_off));
543                        break;
544                    }
545                }
546                _ => {}
547            };
548            last_off = cur + attrs.pos;
549        }
550        if !stack.is_empty() {
551            stack.push(("Wgdevice", cur));
552        }
553        (stack, missing)
554    }
555}
556#[derive(Clone)]
557pub enum Wgpeer<'a> {
558    PublicKey(&'a [u8]),
559    #[doc = "Set as all zeros to remove\\."]
560    PresharedKey(&'a [u8]),
561    #[doc = "\\`\\`0\\`\\` and/or \\`\\`WGPEER\\_F\\_REMOVE\\_ME\\`\\` if the specified peer should not\nexist at the end of the operation, rather than added/updated and/or\n\\`\\`WGPEER\\_F\\_REPLACE\\_ALLOWEDIPS\\`\\` if all current allowed IPs of this\npeer should be removed prior to adding the list below and/or\n\\`\\`WGPEER\\_F\\_UPDATE\\_ONLY\\`\\` if the peer should only be set if it already\nexists\\.\n\nAssociated type: [`WgpeerFlags`] (enum)"]
562    Flags(u32),
563    #[doc = "struct sockaddr\\_in or struct sockaddr\\_in6"]
564    Endpoint(std::net::SocketAddr),
565    #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
566    PersistentKeepaliveInterval(u16),
567    LastHandshakeTime(KernelTimespec),
568    RxBytes(u64),
569    TxBytes(u64),
570    #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
571    Allowedips(IterableArrayWgallowedip<'a>),
572    #[doc = "Should not be set or used at all by most users of this API, as the\nmost recent protocol will be used when this is unset\\. Otherwise,\nmust be set to \\`\\`1\\`\\`\\.\n"]
573    ProtocolVersion(u32),
574}
575impl<'a> IterableWgpeer<'a> {
576    pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
577        let mut iter = self.clone();
578        iter.pos = 0;
579        for attr in iter {
580            if let Wgpeer::PublicKey(val) = attr? {
581                return Ok(val);
582            }
583        }
584        Err(ErrorContext::new_missing(
585            "Wgpeer",
586            "PublicKey",
587            self.orig_loc,
588            self.buf.as_ptr() as usize,
589        ))
590    }
591    #[doc = "Set as all zeros to remove\\."]
592    pub fn get_preshared_key(&self) -> Result<&'a [u8], ErrorContext> {
593        let mut iter = self.clone();
594        iter.pos = 0;
595        for attr in iter {
596            if let Wgpeer::PresharedKey(val) = attr? {
597                return Ok(val);
598            }
599        }
600        Err(ErrorContext::new_missing(
601            "Wgpeer",
602            "PresharedKey",
603            self.orig_loc,
604            self.buf.as_ptr() as usize,
605        ))
606    }
607    #[doc = "\\`\\`0\\`\\` and/or \\`\\`WGPEER\\_F\\_REMOVE\\_ME\\`\\` if the specified peer should not\nexist at the end of the operation, rather than added/updated and/or\n\\`\\`WGPEER\\_F\\_REPLACE\\_ALLOWEDIPS\\`\\` if all current allowed IPs of this\npeer should be removed prior to adding the list below and/or\n\\`\\`WGPEER\\_F\\_UPDATE\\_ONLY\\`\\` if the peer should only be set if it already\nexists\\.\n\nAssociated type: [`WgpeerFlags`] (enum)"]
608    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
609        let mut iter = self.clone();
610        iter.pos = 0;
611        for attr in iter {
612            if let Wgpeer::Flags(val) = attr? {
613                return Ok(val);
614            }
615        }
616        Err(ErrorContext::new_missing(
617            "Wgpeer",
618            "Flags",
619            self.orig_loc,
620            self.buf.as_ptr() as usize,
621        ))
622    }
623    #[doc = "struct sockaddr\\_in or struct sockaddr\\_in6"]
624    pub fn get_endpoint(&self) -> Result<std::net::SocketAddr, ErrorContext> {
625        let mut iter = self.clone();
626        iter.pos = 0;
627        for attr in iter {
628            if let Wgpeer::Endpoint(val) = attr? {
629                return Ok(val);
630            }
631        }
632        Err(ErrorContext::new_missing(
633            "Wgpeer",
634            "Endpoint",
635            self.orig_loc,
636            self.buf.as_ptr() as usize,
637        ))
638    }
639    #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
640    pub fn get_persistent_keepalive_interval(&self) -> Result<u16, ErrorContext> {
641        let mut iter = self.clone();
642        iter.pos = 0;
643        for attr in iter {
644            if let Wgpeer::PersistentKeepaliveInterval(val) = attr? {
645                return Ok(val);
646            }
647        }
648        Err(ErrorContext::new_missing(
649            "Wgpeer",
650            "PersistentKeepaliveInterval",
651            self.orig_loc,
652            self.buf.as_ptr() as usize,
653        ))
654    }
655    pub fn get_last_handshake_time(&self) -> Result<KernelTimespec, ErrorContext> {
656        let mut iter = self.clone();
657        iter.pos = 0;
658        for attr in iter {
659            if let Wgpeer::LastHandshakeTime(val) = attr? {
660                return Ok(val);
661            }
662        }
663        Err(ErrorContext::new_missing(
664            "Wgpeer",
665            "LastHandshakeTime",
666            self.orig_loc,
667            self.buf.as_ptr() as usize,
668        ))
669    }
670    pub fn get_rx_bytes(&self) -> Result<u64, ErrorContext> {
671        let mut iter = self.clone();
672        iter.pos = 0;
673        for attr in iter {
674            if let Wgpeer::RxBytes(val) = attr? {
675                return Ok(val);
676            }
677        }
678        Err(ErrorContext::new_missing(
679            "Wgpeer",
680            "RxBytes",
681            self.orig_loc,
682            self.buf.as_ptr() as usize,
683        ))
684    }
685    pub fn get_tx_bytes(&self) -> Result<u64, ErrorContext> {
686        let mut iter = self.clone();
687        iter.pos = 0;
688        for attr in iter {
689            if let Wgpeer::TxBytes(val) = attr? {
690                return Ok(val);
691            }
692        }
693        Err(ErrorContext::new_missing(
694            "Wgpeer",
695            "TxBytes",
696            self.orig_loc,
697            self.buf.as_ptr() as usize,
698        ))
699    }
700    #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
701    pub fn get_allowedips(
702        &self,
703    ) -> Result<ArrayIterable<IterableArrayWgallowedip<'a>, IterableWgallowedip<'a>>, ErrorContext>
704    {
705        for attr in self.clone() {
706            if let Wgpeer::Allowedips(val) = attr? {
707                return Ok(ArrayIterable::new(val));
708            }
709        }
710        Err(ErrorContext::new_missing(
711            "Wgpeer",
712            "Allowedips",
713            self.orig_loc,
714            self.buf.as_ptr() as usize,
715        ))
716    }
717    #[doc = "Should not be set or used at all by most users of this API, as the\nmost recent protocol will be used when this is unset\\. Otherwise,\nmust be set to \\`\\`1\\`\\`\\.\n"]
718    pub fn get_protocol_version(&self) -> Result<u32, ErrorContext> {
719        let mut iter = self.clone();
720        iter.pos = 0;
721        for attr in iter {
722            if let Wgpeer::ProtocolVersion(val) = attr? {
723                return Ok(val);
724            }
725        }
726        Err(ErrorContext::new_missing(
727            "Wgpeer",
728            "ProtocolVersion",
729            self.orig_loc,
730            self.buf.as_ptr() as usize,
731        ))
732    }
733}
734impl Wgallowedip {
735    pub fn new_array(buf: &[u8]) -> IterableArrayWgallowedip<'_> {
736        IterableArrayWgallowedip::with_loc(buf, buf.as_ptr() as usize)
737    }
738}
739#[derive(Clone, Copy, Default)]
740pub struct IterableArrayWgallowedip<'a> {
741    buf: &'a [u8],
742    pos: usize,
743    orig_loc: usize,
744}
745impl<'a> IterableArrayWgallowedip<'a> {
746    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
747        Self {
748            buf,
749            pos: 0,
750            orig_loc,
751        }
752    }
753    pub fn get_buf(&self) -> &'a [u8] {
754        self.buf
755    }
756}
757impl<'a> Iterator for IterableArrayWgallowedip<'a> {
758    type Item = Result<IterableWgallowedip<'a>, ErrorContext>;
759    fn next(&mut self) -> Option<Self::Item> {
760        if self.buf.len() == self.pos {
761            return None;
762        }
763        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
764            {
765                return Some(Ok(IterableWgallowedip::with_loc(next, self.orig_loc)));
766            }
767        }
768        Some(Err(ErrorContext::new(
769            "Wgallowedip",
770            None,
771            self.orig_loc,
772            self.buf.as_ptr().wrapping_add(self.pos) as usize,
773        )))
774    }
775}
776impl Wgpeer<'_> {
777    pub fn new<'a>(buf: &'a [u8]) -> IterableWgpeer<'a> {
778        IterableWgpeer::with_loc(buf, buf.as_ptr() as usize)
779    }
780    fn attr_from_type(r#type: u16) -> Option<&'static str> {
781        let res = match r#type {
782            0u16 => "Unspec",
783            1u16 => "PublicKey",
784            2u16 => "PresharedKey",
785            3u16 => "Flags",
786            4u16 => "Endpoint",
787            5u16 => "PersistentKeepaliveInterval",
788            6u16 => "LastHandshakeTime",
789            7u16 => "RxBytes",
790            8u16 => "TxBytes",
791            9u16 => "Allowedips",
792            10u16 => "ProtocolVersion",
793            _ => return None,
794        };
795        Some(res)
796    }
797}
798#[derive(Clone, Copy, Default)]
799pub struct IterableWgpeer<'a> {
800    buf: &'a [u8],
801    pos: usize,
802    orig_loc: usize,
803}
804impl<'a> IterableWgpeer<'a> {
805    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
806        Self {
807            buf,
808            pos: 0,
809            orig_loc,
810        }
811    }
812    pub fn get_buf(&self) -> &'a [u8] {
813        self.buf
814    }
815}
816impl<'a> Iterator for IterableWgpeer<'a> {
817    type Item = Result<Wgpeer<'a>, ErrorContext>;
818    fn next(&mut self) -> Option<Self::Item> {
819        let pos = self.pos;
820        let mut r#type;
821        loop {
822            r#type = None;
823            if self.buf.len() == self.pos {
824                return None;
825            }
826            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
827                break;
828            };
829            r#type = Some(header.r#type);
830            let res = match header.r#type {
831                1u16 => Wgpeer::PublicKey({
832                    let res = Some(next);
833                    let Some(val) = res else { break };
834                    val
835                }),
836                2u16 => Wgpeer::PresharedKey({
837                    let res = Some(next);
838                    let Some(val) = res else { break };
839                    val
840                }),
841                3u16 => Wgpeer::Flags({
842                    let res = parse_u32(next);
843                    let Some(val) = res else { break };
844                    val
845                }),
846                4u16 => Wgpeer::Endpoint({
847                    let res = parse_sockaddr(next);
848                    let Some(val) = res else { break };
849                    val
850                }),
851                5u16 => Wgpeer::PersistentKeepaliveInterval({
852                    let res = parse_u16(next);
853                    let Some(val) = res else { break };
854                    val
855                }),
856                6u16 => Wgpeer::LastHandshakeTime({
857                    let res = Some(KernelTimespec::new_from_zeroed(next));
858                    let Some(val) = res else { break };
859                    val
860                }),
861                7u16 => Wgpeer::RxBytes({
862                    let res = parse_u64(next);
863                    let Some(val) = res else { break };
864                    val
865                }),
866                8u16 => Wgpeer::TxBytes({
867                    let res = parse_u64(next);
868                    let Some(val) = res else { break };
869                    val
870                }),
871                9u16 => Wgpeer::Allowedips({
872                    let res = Some(IterableArrayWgallowedip::with_loc(next, self.orig_loc));
873                    let Some(val) = res else { break };
874                    val
875                }),
876                10u16 => Wgpeer::ProtocolVersion({
877                    let res = parse_u32(next);
878                    let Some(val) = res else { break };
879                    val
880                }),
881                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
882                n => continue,
883            };
884            return Some(Ok(res));
885        }
886        Some(Err(ErrorContext::new(
887            "Wgpeer",
888            r#type.and_then(|t| Wgpeer::attr_from_type(t)),
889            self.orig_loc,
890            self.buf.as_ptr().wrapping_add(pos) as usize,
891        )))
892    }
893}
894impl std::fmt::Debug for IterableArrayWgallowedip<'_> {
895    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
896        fmt.debug_list()
897            .entries(self.clone().map(FlattenErrorContext))
898            .finish()
899    }
900}
901impl<'a> std::fmt::Debug for IterableWgpeer<'_> {
902    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
903        let mut fmt = f.debug_struct("Wgpeer");
904        for attr in self.clone() {
905            let attr = match attr {
906                Ok(a) => a,
907                Err(err) => {
908                    fmt.finish()?;
909                    f.write_str("Err(")?;
910                    err.fmt(f)?;
911                    return f.write_str(")");
912                }
913            };
914            match attr {
915                Wgpeer::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
916                Wgpeer::PresharedKey(val) => fmt.field("PresharedKey", &FormatHex(val)),
917                Wgpeer::Flags(val) => {
918                    fmt.field("Flags", &FormatFlags(val.into(), WgpeerFlags::from_value))
919                }
920                Wgpeer::Endpoint(val) => fmt.field("Endpoint", &val),
921                Wgpeer::PersistentKeepaliveInterval(val) => {
922                    fmt.field("PersistentKeepaliveInterval", &val)
923                }
924                Wgpeer::LastHandshakeTime(val) => fmt.field("LastHandshakeTime", &val),
925                Wgpeer::RxBytes(val) => fmt.field("RxBytes", &val),
926                Wgpeer::TxBytes(val) => fmt.field("TxBytes", &val),
927                Wgpeer::Allowedips(val) => fmt.field("Allowedips", &val),
928                Wgpeer::ProtocolVersion(val) => fmt.field("ProtocolVersion", &val),
929            };
930        }
931        fmt.finish()
932    }
933}
934impl IterableWgpeer<'_> {
935    pub fn lookup_attr(
936        &self,
937        offset: usize,
938        missing_type: Option<u16>,
939    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
940        let mut stack = Vec::new();
941        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
942        if missing_type.is_some() && cur == offset {
943            stack.push(("Wgpeer", offset));
944            return (stack, missing_type.and_then(|t| Wgpeer::attr_from_type(t)));
945        }
946        if cur > offset || cur + self.buf.len() < offset {
947            return (stack, None);
948        }
949        let mut attrs = self.clone();
950        let mut last_off = cur + attrs.pos;
951        let mut missing = None;
952        while let Some(attr) = attrs.next() {
953            let Ok(attr) = attr else { break };
954            match attr {
955                Wgpeer::PublicKey(val) => {
956                    if last_off == offset {
957                        stack.push(("PublicKey", last_off));
958                        break;
959                    }
960                }
961                Wgpeer::PresharedKey(val) => {
962                    if last_off == offset {
963                        stack.push(("PresharedKey", last_off));
964                        break;
965                    }
966                }
967                Wgpeer::Flags(val) => {
968                    if last_off == offset {
969                        stack.push(("Flags", last_off));
970                        break;
971                    }
972                }
973                Wgpeer::Endpoint(val) => {
974                    if last_off == offset {
975                        stack.push(("Endpoint", last_off));
976                        break;
977                    }
978                }
979                Wgpeer::PersistentKeepaliveInterval(val) => {
980                    if last_off == offset {
981                        stack.push(("PersistentKeepaliveInterval", last_off));
982                        break;
983                    }
984                }
985                Wgpeer::LastHandshakeTime(val) => {
986                    if last_off == offset {
987                        stack.push(("LastHandshakeTime", last_off));
988                        break;
989                    }
990                }
991                Wgpeer::RxBytes(val) => {
992                    if last_off == offset {
993                        stack.push(("RxBytes", last_off));
994                        break;
995                    }
996                }
997                Wgpeer::TxBytes(val) => {
998                    if last_off == offset {
999                        stack.push(("TxBytes", last_off));
1000                        break;
1001                    }
1002                }
1003                Wgpeer::Allowedips(val) => {
1004                    for entry in val {
1005                        let Ok(attr) = entry else { break };
1006                        (stack, missing) = attr.lookup_attr(offset, missing_type);
1007                        if !stack.is_empty() {
1008                            break;
1009                        }
1010                    }
1011                    if !stack.is_empty() {
1012                        stack.push(("Allowedips", last_off));
1013                        break;
1014                    }
1015                }
1016                Wgpeer::ProtocolVersion(val) => {
1017                    if last_off == offset {
1018                        stack.push(("ProtocolVersion", last_off));
1019                        break;
1020                    }
1021                }
1022                _ => {}
1023            };
1024            last_off = cur + attrs.pos;
1025        }
1026        if !stack.is_empty() {
1027            stack.push(("Wgpeer", cur));
1028        }
1029        (stack, missing)
1030    }
1031}
1032#[derive(Clone)]
1033pub enum Wgallowedip {
1034    #[doc = "IP family, either \\`\\`AF\\_INET\\`\\` or \\`\\`AF\\_INET6\\`\\`\\."]
1035    Family(u16),
1036    #[doc = "Either \\`\\`struct in\\_addr\\`\\` or \\`\\`struct in6\\_addr\\`\\`\\."]
1037    Ipaddr(std::net::IpAddr),
1038    CidrMask(u8),
1039    #[doc = "\\`\\`WGALLOWEDIP\\_F\\_REMOVE\\_ME\\`\\` if the specified IP should be removed;\notherwise, this IP will be added if it is not already present\\.\n\nAssociated type: [`WgallowedipFlags`] (enum)"]
1040    Flags(u32),
1041}
1042impl<'a> IterableWgallowedip<'a> {
1043    #[doc = "IP family, either \\`\\`AF\\_INET\\`\\` or \\`\\`AF\\_INET6\\`\\`\\."]
1044    pub fn get_family(&self) -> Result<u16, ErrorContext> {
1045        let mut iter = self.clone();
1046        iter.pos = 0;
1047        for attr in iter {
1048            if let Wgallowedip::Family(val) = attr? {
1049                return Ok(val);
1050            }
1051        }
1052        Err(ErrorContext::new_missing(
1053            "Wgallowedip",
1054            "Family",
1055            self.orig_loc,
1056            self.buf.as_ptr() as usize,
1057        ))
1058    }
1059    #[doc = "Either \\`\\`struct in\\_addr\\`\\` or \\`\\`struct in6\\_addr\\`\\`\\."]
1060    pub fn get_ipaddr(&self) -> Result<std::net::IpAddr, ErrorContext> {
1061        let mut iter = self.clone();
1062        iter.pos = 0;
1063        for attr in iter {
1064            if let Wgallowedip::Ipaddr(val) = attr? {
1065                return Ok(val);
1066            }
1067        }
1068        Err(ErrorContext::new_missing(
1069            "Wgallowedip",
1070            "Ipaddr",
1071            self.orig_loc,
1072            self.buf.as_ptr() as usize,
1073        ))
1074    }
1075    pub fn get_cidr_mask(&self) -> Result<u8, ErrorContext> {
1076        let mut iter = self.clone();
1077        iter.pos = 0;
1078        for attr in iter {
1079            if let Wgallowedip::CidrMask(val) = attr? {
1080                return Ok(val);
1081            }
1082        }
1083        Err(ErrorContext::new_missing(
1084            "Wgallowedip",
1085            "CidrMask",
1086            self.orig_loc,
1087            self.buf.as_ptr() as usize,
1088        ))
1089    }
1090    #[doc = "\\`\\`WGALLOWEDIP\\_F\\_REMOVE\\_ME\\`\\` if the specified IP should be removed;\notherwise, this IP will be added if it is not already present\\.\n\nAssociated type: [`WgallowedipFlags`] (enum)"]
1091    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
1092        let mut iter = self.clone();
1093        iter.pos = 0;
1094        for attr in iter {
1095            if let Wgallowedip::Flags(val) = attr? {
1096                return Ok(val);
1097            }
1098        }
1099        Err(ErrorContext::new_missing(
1100            "Wgallowedip",
1101            "Flags",
1102            self.orig_loc,
1103            self.buf.as_ptr() as usize,
1104        ))
1105    }
1106}
1107impl Wgallowedip {
1108    pub fn new<'a>(buf: &'a [u8]) -> IterableWgallowedip<'a> {
1109        IterableWgallowedip::with_loc(buf, buf.as_ptr() as usize)
1110    }
1111    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1112        let res = match r#type {
1113            0u16 => "Unspec",
1114            1u16 => "Family",
1115            2u16 => "Ipaddr",
1116            3u16 => "CidrMask",
1117            4u16 => "Flags",
1118            _ => return None,
1119        };
1120        Some(res)
1121    }
1122}
1123#[derive(Clone, Copy, Default)]
1124pub struct IterableWgallowedip<'a> {
1125    buf: &'a [u8],
1126    pos: usize,
1127    orig_loc: usize,
1128}
1129impl<'a> IterableWgallowedip<'a> {
1130    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1131        Self {
1132            buf,
1133            pos: 0,
1134            orig_loc,
1135        }
1136    }
1137    pub fn get_buf(&self) -> &'a [u8] {
1138        self.buf
1139    }
1140}
1141impl<'a> Iterator for IterableWgallowedip<'a> {
1142    type Item = Result<Wgallowedip, ErrorContext>;
1143    fn next(&mut self) -> Option<Self::Item> {
1144        let pos = self.pos;
1145        let mut r#type;
1146        loop {
1147            r#type = None;
1148            if self.buf.len() == self.pos {
1149                return None;
1150            }
1151            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1152                break;
1153            };
1154            r#type = Some(header.r#type);
1155            let res = match header.r#type {
1156                1u16 => Wgallowedip::Family({
1157                    let res = parse_u16(next);
1158                    let Some(val) = res else { break };
1159                    val
1160                }),
1161                2u16 => Wgallowedip::Ipaddr({
1162                    let res = parse_ip(next);
1163                    let Some(val) = res else { break };
1164                    val
1165                }),
1166                3u16 => Wgallowedip::CidrMask({
1167                    let res = parse_u8(next);
1168                    let Some(val) = res else { break };
1169                    val
1170                }),
1171                4u16 => Wgallowedip::Flags({
1172                    let res = parse_u32(next);
1173                    let Some(val) = res else { break };
1174                    val
1175                }),
1176                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1177                n => continue,
1178            };
1179            return Some(Ok(res));
1180        }
1181        Some(Err(ErrorContext::new(
1182            "Wgallowedip",
1183            r#type.and_then(|t| Wgallowedip::attr_from_type(t)),
1184            self.orig_loc,
1185            self.buf.as_ptr().wrapping_add(pos) as usize,
1186        )))
1187    }
1188}
1189impl std::fmt::Debug for IterableWgallowedip<'_> {
1190    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1191        let mut fmt = f.debug_struct("Wgallowedip");
1192        for attr in self.clone() {
1193            let attr = match attr {
1194                Ok(a) => a,
1195                Err(err) => {
1196                    fmt.finish()?;
1197                    f.write_str("Err(")?;
1198                    err.fmt(f)?;
1199                    return f.write_str(")");
1200                }
1201            };
1202            match attr {
1203                Wgallowedip::Family(val) => fmt.field("Family", &val),
1204                Wgallowedip::Ipaddr(val) => fmt.field("Ipaddr", &val),
1205                Wgallowedip::CidrMask(val) => fmt.field("CidrMask", &val),
1206                Wgallowedip::Flags(val) => fmt.field(
1207                    "Flags",
1208                    &FormatFlags(val.into(), WgallowedipFlags::from_value),
1209                ),
1210            };
1211        }
1212        fmt.finish()
1213    }
1214}
1215impl IterableWgallowedip<'_> {
1216    pub fn lookup_attr(
1217        &self,
1218        offset: usize,
1219        missing_type: Option<u16>,
1220    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1221        let mut stack = Vec::new();
1222        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1223        if missing_type.is_some() && cur == offset {
1224            stack.push(("Wgallowedip", offset));
1225            return (
1226                stack,
1227                missing_type.and_then(|t| Wgallowedip::attr_from_type(t)),
1228            );
1229        }
1230        if cur > offset || cur + self.buf.len() < offset {
1231            return (stack, None);
1232        }
1233        let mut attrs = self.clone();
1234        let mut last_off = cur + attrs.pos;
1235        while let Some(attr) = attrs.next() {
1236            let Ok(attr) = attr else { break };
1237            match attr {
1238                Wgallowedip::Family(val) => {
1239                    if last_off == offset {
1240                        stack.push(("Family", last_off));
1241                        break;
1242                    }
1243                }
1244                Wgallowedip::Ipaddr(val) => {
1245                    if last_off == offset {
1246                        stack.push(("Ipaddr", last_off));
1247                        break;
1248                    }
1249                }
1250                Wgallowedip::CidrMask(val) => {
1251                    if last_off == offset {
1252                        stack.push(("CidrMask", last_off));
1253                        break;
1254                    }
1255                }
1256                Wgallowedip::Flags(val) => {
1257                    if last_off == offset {
1258                        stack.push(("Flags", last_off));
1259                        break;
1260                    }
1261                }
1262                _ => {}
1263            };
1264            last_off = cur + attrs.pos;
1265        }
1266        if !stack.is_empty() {
1267            stack.push(("Wgallowedip", cur));
1268        }
1269        (stack, None)
1270    }
1271}
1272pub struct PushWgdevice<Prev: Rec> {
1273    pub(crate) prev: Option<Prev>,
1274    pub(crate) header_offset: Option<usize>,
1275}
1276impl<Prev: Rec> Rec for PushWgdevice<Prev> {
1277    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1278        self.prev.as_mut().unwrap().as_rec_mut()
1279    }
1280    fn as_rec(&self) -> &Vec<u8> {
1281        self.prev.as_ref().unwrap().as_rec()
1282    }
1283}
1284pub struct PushArrayWgpeer<Prev: Rec> {
1285    pub(crate) prev: Option<Prev>,
1286    pub(crate) header_offset: Option<usize>,
1287    pub(crate) counter: u16,
1288}
1289impl<Prev: Rec> Rec for PushArrayWgpeer<Prev> {
1290    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1291        self.prev.as_mut().unwrap().as_rec_mut()
1292    }
1293    fn as_rec(&self) -> &Vec<u8> {
1294        self.prev.as_ref().unwrap().as_rec()
1295    }
1296}
1297impl<Prev: Rec> PushArrayWgpeer<Prev> {
1298    pub fn new(prev: Prev) -> Self {
1299        Self {
1300            prev: Some(prev),
1301            header_offset: None,
1302            counter: 0,
1303        }
1304    }
1305    pub fn end_array(mut self) -> Prev {
1306        let mut prev = self.prev.take().unwrap();
1307        if let Some(header_offset) = &self.header_offset {
1308            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1309        }
1310        prev
1311    }
1312    pub fn entry_nested(mut self) -> PushWgpeer<Self> {
1313        let index = self.counter;
1314        self.counter += 1;
1315        let header_offset = push_nested_header(self.as_rec_mut(), index);
1316        PushWgpeer {
1317            prev: Some(self),
1318            header_offset: Some(header_offset),
1319        }
1320    }
1321}
1322impl<Prev: Rec> Drop for PushArrayWgpeer<Prev> {
1323    fn drop(&mut self) {
1324        if let Some(prev) = &mut self.prev {
1325            if let Some(header_offset) = &self.header_offset {
1326                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1327            }
1328        }
1329    }
1330}
1331impl<Prev: Rec> PushWgdevice<Prev> {
1332    pub fn new(prev: Prev) -> Self {
1333        Self {
1334            prev: Some(prev),
1335            header_offset: None,
1336        }
1337    }
1338    pub fn end_nested(mut self) -> Prev {
1339        let mut prev = self.prev.take().unwrap();
1340        if let Some(header_offset) = &self.header_offset {
1341            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1342        }
1343        prev
1344    }
1345    pub fn push_ifindex(mut self, value: u32) -> Self {
1346        push_header(self.as_rec_mut(), 1u16, 4 as u16);
1347        self.as_rec_mut().extend(value.to_ne_bytes());
1348        self
1349    }
1350    pub fn push_ifname(mut self, value: &CStr) -> Self {
1351        push_header(
1352            self.as_rec_mut(),
1353            2u16,
1354            value.to_bytes_with_nul().len() as u16,
1355        );
1356        self.as_rec_mut().extend(value.to_bytes_with_nul());
1357        self
1358    }
1359    pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
1360        push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
1361        self.as_rec_mut().extend(value);
1362        self.as_rec_mut().push(0);
1363        self
1364    }
1365    #[doc = "Set to all zeros to remove\\."]
1366    pub fn push_private_key(mut self, value: &[u8]) -> Self {
1367        push_header(self.as_rec_mut(), 3u16, value.len() as u16);
1368        self.as_rec_mut().extend(value);
1369        self
1370    }
1371    pub fn push_public_key(mut self, value: &[u8]) -> Self {
1372        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
1373        self.as_rec_mut().extend(value);
1374        self
1375    }
1376    #[doc = "\\`\\`0\\`\\` or \\`\\`WGDEVICE\\_F\\_REPLACE\\_PEERS\\`\\` if all current peers should be\nremoved prior to adding the list below\\.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
1377    pub fn push_flags(mut self, value: u32) -> Self {
1378        push_header(self.as_rec_mut(), 5u16, 4 as u16);
1379        self.as_rec_mut().extend(value.to_ne_bytes());
1380        self
1381    }
1382    #[doc = "Set as \\`\\`0\\`\\` to choose randomly\\."]
1383    pub fn push_listen_port(mut self, value: u16) -> Self {
1384        push_header(self.as_rec_mut(), 6u16, 2 as u16);
1385        self.as_rec_mut().extend(value.to_ne_bytes());
1386        self
1387    }
1388    #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
1389    pub fn push_fwmark(mut self, value: u32) -> Self {
1390        push_header(self.as_rec_mut(), 7u16, 4 as u16);
1391        self.as_rec_mut().extend(value.to_ne_bytes());
1392        self
1393    }
1394    #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
1395    pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
1396        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
1397        PushArrayWgpeer {
1398            prev: Some(self),
1399            header_offset: Some(header_offset),
1400            counter: 0,
1401        }
1402    }
1403}
1404impl<Prev: Rec> Drop for PushWgdevice<Prev> {
1405    fn drop(&mut self) {
1406        if let Some(prev) = &mut self.prev {
1407            if let Some(header_offset) = &self.header_offset {
1408                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1409            }
1410        }
1411    }
1412}
1413pub struct PushWgpeer<Prev: Rec> {
1414    pub(crate) prev: Option<Prev>,
1415    pub(crate) header_offset: Option<usize>,
1416}
1417impl<Prev: Rec> Rec for PushWgpeer<Prev> {
1418    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1419        self.prev.as_mut().unwrap().as_rec_mut()
1420    }
1421    fn as_rec(&self) -> &Vec<u8> {
1422        self.prev.as_ref().unwrap().as_rec()
1423    }
1424}
1425pub struct PushArrayWgallowedip<Prev: Rec> {
1426    pub(crate) prev: Option<Prev>,
1427    pub(crate) header_offset: Option<usize>,
1428    pub(crate) counter: u16,
1429}
1430impl<Prev: Rec> Rec for PushArrayWgallowedip<Prev> {
1431    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1432        self.prev.as_mut().unwrap().as_rec_mut()
1433    }
1434    fn as_rec(&self) -> &Vec<u8> {
1435        self.prev.as_ref().unwrap().as_rec()
1436    }
1437}
1438impl<Prev: Rec> PushArrayWgallowedip<Prev> {
1439    pub fn new(prev: Prev) -> Self {
1440        Self {
1441            prev: Some(prev),
1442            header_offset: None,
1443            counter: 0,
1444        }
1445    }
1446    pub fn end_array(mut self) -> Prev {
1447        let mut prev = self.prev.take().unwrap();
1448        if let Some(header_offset) = &self.header_offset {
1449            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1450        }
1451        prev
1452    }
1453    pub fn entry_nested(mut self) -> PushWgallowedip<Self> {
1454        let index = self.counter;
1455        self.counter += 1;
1456        let header_offset = push_nested_header(self.as_rec_mut(), index);
1457        PushWgallowedip {
1458            prev: Some(self),
1459            header_offset: Some(header_offset),
1460        }
1461    }
1462}
1463impl<Prev: Rec> Drop for PushArrayWgallowedip<Prev> {
1464    fn drop(&mut self) {
1465        if let Some(prev) = &mut self.prev {
1466            if let Some(header_offset) = &self.header_offset {
1467                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1468            }
1469        }
1470    }
1471}
1472impl<Prev: Rec> PushWgpeer<Prev> {
1473    pub fn new(prev: Prev) -> Self {
1474        Self {
1475            prev: Some(prev),
1476            header_offset: None,
1477        }
1478    }
1479    pub fn end_nested(mut self) -> Prev {
1480        let mut prev = self.prev.take().unwrap();
1481        if let Some(header_offset) = &self.header_offset {
1482            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1483        }
1484        prev
1485    }
1486    pub fn push_public_key(mut self, value: &[u8]) -> Self {
1487        push_header(self.as_rec_mut(), 1u16, value.len() as u16);
1488        self.as_rec_mut().extend(value);
1489        self
1490    }
1491    #[doc = "Set as all zeros to remove\\."]
1492    pub fn push_preshared_key(mut self, value: &[u8]) -> Self {
1493        push_header(self.as_rec_mut(), 2u16, value.len() as u16);
1494        self.as_rec_mut().extend(value);
1495        self
1496    }
1497    #[doc = "\\`\\`0\\`\\` and/or \\`\\`WGPEER\\_F\\_REMOVE\\_ME\\`\\` if the specified peer should not\nexist at the end of the operation, rather than added/updated and/or\n\\`\\`WGPEER\\_F\\_REPLACE\\_ALLOWEDIPS\\`\\` if all current allowed IPs of this\npeer should be removed prior to adding the list below and/or\n\\`\\`WGPEER\\_F\\_UPDATE\\_ONLY\\`\\` if the peer should only be set if it already\nexists\\.\n\nAssociated type: [`WgpeerFlags`] (enum)"]
1498    pub fn push_flags(mut self, value: u32) -> Self {
1499        push_header(self.as_rec_mut(), 3u16, 4 as u16);
1500        self.as_rec_mut().extend(value.to_ne_bytes());
1501        self
1502    }
1503    #[doc = "struct sockaddr\\_in or struct sockaddr\\_in6"]
1504    pub fn push_endpoint(mut self, value: std::net::SocketAddr) -> Self {
1505        push_header(self.as_rec_mut(), 4u16, {
1506            match &value {
1507                SocketAddr::V4(_) => 16,
1508                SocketAddr::V6(_) => 28,
1509            }
1510        } as u16);
1511        encode_sockaddr(self.as_rec_mut(), value);
1512        self
1513    }
1514    #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
1515    pub fn push_persistent_keepalive_interval(mut self, value: u16) -> Self {
1516        push_header(self.as_rec_mut(), 5u16, 2 as u16);
1517        self.as_rec_mut().extend(value.to_ne_bytes());
1518        self
1519    }
1520    pub fn push_last_handshake_time(mut self, value: KernelTimespec) -> Self {
1521        push_header(self.as_rec_mut(), 6u16, value.as_slice().len() as u16);
1522        self.as_rec_mut().extend(value.as_slice());
1523        self
1524    }
1525    pub fn push_rx_bytes(mut self, value: u64) -> Self {
1526        push_header(self.as_rec_mut(), 7u16, 8 as u16);
1527        self.as_rec_mut().extend(value.to_ne_bytes());
1528        self
1529    }
1530    pub fn push_tx_bytes(mut self, value: u64) -> Self {
1531        push_header(self.as_rec_mut(), 8u16, 8 as u16);
1532        self.as_rec_mut().extend(value.to_ne_bytes());
1533        self
1534    }
1535    #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
1536    pub fn array_allowedips(mut self) -> PushArrayWgallowedip<Self> {
1537        let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
1538        PushArrayWgallowedip {
1539            prev: Some(self),
1540            header_offset: Some(header_offset),
1541            counter: 0,
1542        }
1543    }
1544    #[doc = "Should not be set or used at all by most users of this API, as the\nmost recent protocol will be used when this is unset\\. Otherwise,\nmust be set to \\`\\`1\\`\\`\\.\n"]
1545    pub fn push_protocol_version(mut self, value: u32) -> Self {
1546        push_header(self.as_rec_mut(), 10u16, 4 as u16);
1547        self.as_rec_mut().extend(value.to_ne_bytes());
1548        self
1549    }
1550}
1551impl<Prev: Rec> Drop for PushWgpeer<Prev> {
1552    fn drop(&mut self) {
1553        if let Some(prev) = &mut self.prev {
1554            if let Some(header_offset) = &self.header_offset {
1555                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1556            }
1557        }
1558    }
1559}
1560pub struct PushWgallowedip<Prev: Rec> {
1561    pub(crate) prev: Option<Prev>,
1562    pub(crate) header_offset: Option<usize>,
1563}
1564impl<Prev: Rec> Rec for PushWgallowedip<Prev> {
1565    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1566        self.prev.as_mut().unwrap().as_rec_mut()
1567    }
1568    fn as_rec(&self) -> &Vec<u8> {
1569        self.prev.as_ref().unwrap().as_rec()
1570    }
1571}
1572impl<Prev: Rec> PushWgallowedip<Prev> {
1573    pub fn new(prev: Prev) -> Self {
1574        Self {
1575            prev: Some(prev),
1576            header_offset: None,
1577        }
1578    }
1579    pub fn end_nested(mut self) -> Prev {
1580        let mut prev = self.prev.take().unwrap();
1581        if let Some(header_offset) = &self.header_offset {
1582            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1583        }
1584        prev
1585    }
1586    #[doc = "IP family, either \\`\\`AF\\_INET\\`\\` or \\`\\`AF\\_INET6\\`\\`\\."]
1587    pub fn push_family(mut self, value: u16) -> Self {
1588        push_header(self.as_rec_mut(), 1u16, 2 as u16);
1589        self.as_rec_mut().extend(value.to_ne_bytes());
1590        self
1591    }
1592    #[doc = "Either \\`\\`struct in\\_addr\\`\\` or \\`\\`struct in6\\_addr\\`\\`\\."]
1593    pub fn push_ipaddr(mut self, value: std::net::IpAddr) -> Self {
1594        push_header(self.as_rec_mut(), 2u16, {
1595            match &value {
1596                IpAddr::V4(_) => 4,
1597                IpAddr::V6(_) => 16,
1598            }
1599        } as u16);
1600        encode_ip(self.as_rec_mut(), value);
1601        self
1602    }
1603    pub fn push_cidr_mask(mut self, value: u8) -> Self {
1604        push_header(self.as_rec_mut(), 3u16, 1 as u16);
1605        self.as_rec_mut().extend(value.to_ne_bytes());
1606        self
1607    }
1608    #[doc = "\\`\\`WGALLOWEDIP\\_F\\_REMOVE\\_ME\\`\\` if the specified IP should be removed;\notherwise, this IP will be added if it is not already present\\.\n\nAssociated type: [`WgallowedipFlags`] (enum)"]
1609    pub fn push_flags(mut self, value: u32) -> Self {
1610        push_header(self.as_rec_mut(), 4u16, 4 as u16);
1611        self.as_rec_mut().extend(value.to_ne_bytes());
1612        self
1613    }
1614}
1615impl<Prev: Rec> Drop for PushWgallowedip<Prev> {
1616    fn drop(&mut self) {
1617        if let Some(prev) = &mut self.prev {
1618            if let Some(header_offset) = &self.header_offset {
1619                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1620            }
1621        }
1622    }
1623}
1624#[doc = "Retrieve WireGuard device\n\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\n\nThe command should be called with one but not both of:\n\n\\- \\`\\`WGDEVICE\\_A\\_IFINDEX\\`\\`\n\\- \\`\\`WGDEVICE\\_A\\_IFNAME\\`\\`\n\nThe kernel will then return several messages (\\`\\`NLM\\_F\\_MULTI\\`\\`)\\. It is\npossible that all of the allowed IPs of a single peer will not fit\nwithin a single netlink message\\. In that case, the same peer will be\nwritten in the following message, except it will only contain\n\\`\\`WGPEER\\_A\\_PUBLIC\\_KEY\\`\\` and \\`\\`WGPEER\\_A\\_ALLOWEDIPS\\`\\`\\. This may occur\nseveral times in a row for the same peer\\. It is then up to the receiver\nto coalesce adjacent peers\\. Likewise, it is possible that all peers will\nnot fit within a single message\\. So, subsequent peers will be sent in\nfollowing messages, except those will only contain \\`\\`WGDEVICE\\_A\\_IFNAME\\`\\`\nand \\`\\`WGDEVICE\\_A\\_PEERS\\`\\`\\. It is then up to the receiver to coalesce\nthese messages to form the complete list of peers\\.\n\nSince this is an \\`\\`NLA\\_F\\_DUMP\\`\\` command, the final message will always\nbe \\`\\`NLMSG\\_DONE\\`\\`, even if an error occurs\\. However, this \\`\\`NLMSG\\_DONE\\`\\`\nmessage contains an integer error code\\. It is either zero or a negative\nerror code corresponding to the errno\\.\n\nFlags: uns-admin-perm\nRequest attributes:\n- [.push_ifindex()](PushWgdevice::push_ifindex)\n- [.push_ifname()](PushWgdevice::push_ifname)\n\nReply attributes:\n- [.get_ifindex()](IterableWgdevice::get_ifindex)\n- [.get_ifname()](IterableWgdevice::get_ifname)\n- [.get_private_key()](IterableWgdevice::get_private_key)\n- [.get_public_key()](IterableWgdevice::get_public_key)\n- [.get_flags()](IterableWgdevice::get_flags)\n- [.get_listen_port()](IterableWgdevice::get_listen_port)\n- [.get_fwmark()](IterableWgdevice::get_fwmark)\n- [.get_peers()](IterableWgdevice::get_peers)\n"]
1625#[derive(Debug)]
1626pub struct OpGetDeviceDump<'r> {
1627    request: Request<'r>,
1628}
1629impl<'r> OpGetDeviceDump<'r> {
1630    pub fn new(mut request: Request<'r>) -> Self {
1631        Self::write_header(request.buf_mut());
1632        Self {
1633            request: request.set_dump(),
1634        }
1635    }
1636    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushWgdevice<&'buf mut Vec<u8>> {
1637        Self::write_header(buf);
1638        PushWgdevice::new(buf)
1639    }
1640    pub fn encode(&mut self) -> PushWgdevice<&mut Vec<u8>> {
1641        PushWgdevice::new(self.request.buf_mut())
1642    }
1643    pub fn into_encoder(self) -> PushWgdevice<RequestBuf<'r>> {
1644        PushWgdevice::new(self.request.buf)
1645    }
1646    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
1647        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1648        IterableWgdevice::with_loc(attrs, buf.as_ptr() as usize)
1649    }
1650    fn write_header<Prev: Rec>(prev: &mut Prev) {
1651        let mut header = BuiltinNfgenmsg::new();
1652        header.cmd = 0u8;
1653        header.version = 1u8;
1654        prev.as_rec_mut().extend(header.as_slice());
1655    }
1656}
1657impl NetlinkRequest for OpGetDeviceDump<'_> {
1658    fn protocol(&self) -> Protocol {
1659        Protocol::Generic("wireguard".as_bytes())
1660    }
1661    fn flags(&self) -> u16 {
1662        self.request.flags
1663    }
1664    fn payload(&self) -> &[u8] {
1665        self.request.buf()
1666    }
1667    type ReplyType<'buf> = IterableWgdevice<'buf>;
1668    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1669        Self::decode_request(buf)
1670    }
1671    fn lookup(
1672        buf: &[u8],
1673        offset: usize,
1674        missing_type: Option<u16>,
1675    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1676        Self::decode_request(buf).lookup_attr(offset, missing_type)
1677    }
1678}
1679#[doc = "Set WireGuard device\n\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\n\nThis command should be called with a wgdevice set, containing one but\nnot both of \\`\\`WGDEVICE\\_A\\_IFINDEX\\`\\` and \\`\\`WGDEVICE\\_A\\_IFNAME\\`\\`\\.\n\nIt is possible that the amount of configuration data exceeds that of the\nmaximum message length accepted by the kernel\\. In that case, several\nmessages should be sent one after another, with each successive one\nfilling in information not contained in the prior\\. Note that if\n\\`\\`WGDEVICE\\_F\\_REPLACE\\_PEERS\\`\\` is specified in the first message, it\nprobably should not be specified in fragments that come after, so that\nthe list of peers is only cleared the first time but appended after\\.\nLikewise for peers, if \\`\\`WGPEER\\_F\\_REPLACE\\_ALLOWEDIPS\\`\\` is specified in\nthe first message of a peer, it likely should not be specified in\nsubsequent fragments\\.\n\nIf an error occurs, \\`\\`NLMSG\\_ERROR\\`\\` will reply containing an errno\\.\n\nFlags: uns-admin-perm\nRequest attributes:\n- [.push_ifindex()](PushWgdevice::push_ifindex)\n- [.push_ifname()](PushWgdevice::push_ifname)\n- [.push_private_key()](PushWgdevice::push_private_key)\n- [.push_public_key()](PushWgdevice::push_public_key)\n- [.push_flags()](PushWgdevice::push_flags)\n- [.push_listen_port()](PushWgdevice::push_listen_port)\n- [.push_fwmark()](PushWgdevice::push_fwmark)\n- [.array_peers()](PushWgdevice::array_peers)\n"]
1680#[derive(Debug)]
1681pub struct OpSetDeviceDo<'r> {
1682    request: Request<'r>,
1683}
1684impl<'r> OpSetDeviceDo<'r> {
1685    pub fn new(mut request: Request<'r>) -> Self {
1686        Self::write_header(request.buf_mut());
1687        Self { request: request }
1688    }
1689    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushWgdevice<&'buf mut Vec<u8>> {
1690        Self::write_header(buf);
1691        PushWgdevice::new(buf)
1692    }
1693    pub fn encode(&mut self) -> PushWgdevice<&mut Vec<u8>> {
1694        PushWgdevice::new(self.request.buf_mut())
1695    }
1696    pub fn into_encoder(self) -> PushWgdevice<RequestBuf<'r>> {
1697        PushWgdevice::new(self.request.buf)
1698    }
1699    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
1700        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1701        IterableWgdevice::with_loc(attrs, buf.as_ptr() as usize)
1702    }
1703    fn write_header<Prev: Rec>(prev: &mut Prev) {
1704        let mut header = BuiltinNfgenmsg::new();
1705        header.cmd = 1u8;
1706        header.version = 1u8;
1707        prev.as_rec_mut().extend(header.as_slice());
1708    }
1709}
1710impl NetlinkRequest for OpSetDeviceDo<'_> {
1711    fn protocol(&self) -> Protocol {
1712        Protocol::Generic("wireguard".as_bytes())
1713    }
1714    fn flags(&self) -> u16 {
1715        self.request.flags
1716    }
1717    fn payload(&self) -> &[u8] {
1718        self.request.buf()
1719    }
1720    type ReplyType<'buf> = IterableWgdevice<'buf>;
1721    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1722        Self::decode_request(buf)
1723    }
1724    fn lookup(
1725        buf: &[u8],
1726        offset: usize,
1727        missing_type: Option<u16>,
1728    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1729        Self::decode_request(buf).lookup_attr(offset, missing_type)
1730    }
1731}
1732use crate::traits::LookupFn;
1733use crate::utils::RequestBuf;
1734#[derive(Debug)]
1735pub struct Request<'buf> {
1736    buf: RequestBuf<'buf>,
1737    flags: u16,
1738    writeback: Option<&'buf mut Option<RequestInfo>>,
1739}
1740#[allow(unused)]
1741#[derive(Debug, Clone)]
1742pub struct RequestInfo {
1743    protocol: Protocol,
1744    flags: u16,
1745    name: &'static str,
1746    lookup: LookupFn,
1747}
1748impl Request<'static> {
1749    pub fn new() -> Self {
1750        Self::new_from_buf(Vec::new())
1751    }
1752    pub fn new_from_buf(buf: Vec<u8>) -> Self {
1753        Self {
1754            flags: 0,
1755            buf: RequestBuf::Own(buf),
1756            writeback: None,
1757        }
1758    }
1759    pub fn into_buf(self) -> Vec<u8> {
1760        match self.buf {
1761            RequestBuf::Own(buf) => buf,
1762            _ => unreachable!(),
1763        }
1764    }
1765}
1766impl<'buf> Request<'buf> {
1767    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1768        buf.clear();
1769        Self::new_extend(buf)
1770    }
1771    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1772        Self {
1773            flags: 0,
1774            buf: RequestBuf::Ref(buf),
1775            writeback: None,
1776        }
1777    }
1778    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1779        let Some(writeback) = &mut self.writeback else {
1780            return;
1781        };
1782        **writeback = Some(RequestInfo {
1783            protocol,
1784            flags: self.flags,
1785            name,
1786            lookup,
1787        })
1788    }
1789    pub fn buf(&self) -> &Vec<u8> {
1790        self.buf.buf()
1791    }
1792    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1793        self.buf.buf_mut()
1794    }
1795    #[doc = "Set `NLM_F_CREATE` flag"]
1796    pub fn set_create(mut self) -> Self {
1797        self.flags |= consts::NLM_F_CREATE as u16;
1798        self
1799    }
1800    #[doc = "Set `NLM_F_EXCL` flag"]
1801    pub fn set_excl(mut self) -> Self {
1802        self.flags |= consts::NLM_F_EXCL as u16;
1803        self
1804    }
1805    #[doc = "Set `NLM_F_REPLACE` flag"]
1806    pub fn set_replace(mut self) -> Self {
1807        self.flags |= consts::NLM_F_REPLACE as u16;
1808        self
1809    }
1810    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1811    pub fn set_change(self) -> Self {
1812        self.set_create().set_replace()
1813    }
1814    #[doc = "Set `NLM_F_APPEND` flag"]
1815    pub fn set_append(mut self) -> Self {
1816        self.flags |= consts::NLM_F_APPEND as u16;
1817        self
1818    }
1819    #[doc = "Set `self.flags |= flags`"]
1820    pub fn set_flags(mut self, flags: u16) -> Self {
1821        self.flags |= flags;
1822        self
1823    }
1824    #[doc = "Set `self.flags ^= self.flags & flags`"]
1825    pub fn unset_flags(mut self, flags: u16) -> Self {
1826        self.flags ^= self.flags & flags;
1827        self
1828    }
1829    #[doc = "Set `NLM_F_DUMP` flag"]
1830    fn set_dump(mut self) -> Self {
1831        self.flags |= consts::NLM_F_DUMP as u16;
1832        self
1833    }
1834    #[doc = "Retrieve WireGuard device\n\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\n\nThe command should be called with one but not both of:\n\n\\- \\`\\`WGDEVICE\\_A\\_IFINDEX\\`\\`\n\\- \\`\\`WGDEVICE\\_A\\_IFNAME\\`\\`\n\nThe kernel will then return several messages (\\`\\`NLM\\_F\\_MULTI\\`\\`)\\. It is\npossible that all of the allowed IPs of a single peer will not fit\nwithin a single netlink message\\. In that case, the same peer will be\nwritten in the following message, except it will only contain\n\\`\\`WGPEER\\_A\\_PUBLIC\\_KEY\\`\\` and \\`\\`WGPEER\\_A\\_ALLOWEDIPS\\`\\`\\. This may occur\nseveral times in a row for the same peer\\. It is then up to the receiver\nto coalesce adjacent peers\\. Likewise, it is possible that all peers will\nnot fit within a single message\\. So, subsequent peers will be sent in\nfollowing messages, except those will only contain \\`\\`WGDEVICE\\_A\\_IFNAME\\`\\`\nand \\`\\`WGDEVICE\\_A\\_PEERS\\`\\`\\. It is then up to the receiver to coalesce\nthese messages to form the complete list of peers\\.\n\nSince this is an \\`\\`NLA\\_F\\_DUMP\\`\\` command, the final message will always\nbe \\`\\`NLMSG\\_DONE\\`\\`, even if an error occurs\\. However, this \\`\\`NLMSG\\_DONE\\`\\`\nmessage contains an integer error code\\. It is either zero or a negative\nerror code corresponding to the errno\\.\n\nFlags: uns-admin-perm\nRequest attributes:\n- [.push_ifindex()](PushWgdevice::push_ifindex)\n- [.push_ifname()](PushWgdevice::push_ifname)\n\nReply attributes:\n- [.get_ifindex()](IterableWgdevice::get_ifindex)\n- [.get_ifname()](IterableWgdevice::get_ifname)\n- [.get_private_key()](IterableWgdevice::get_private_key)\n- [.get_public_key()](IterableWgdevice::get_public_key)\n- [.get_flags()](IterableWgdevice::get_flags)\n- [.get_listen_port()](IterableWgdevice::get_listen_port)\n- [.get_fwmark()](IterableWgdevice::get_fwmark)\n- [.get_peers()](IterableWgdevice::get_peers)\n"]
1835    pub fn op_get_device_dump(self) -> OpGetDeviceDump<'buf> {
1836        let mut res = OpGetDeviceDump::new(self);
1837        res.request.do_writeback(
1838            res.protocol(),
1839            "op-get-device-dump",
1840            OpGetDeviceDump::lookup,
1841        );
1842        res
1843    }
1844    #[doc = "Set WireGuard device\n\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\n\nThis command should be called with a wgdevice set, containing one but\nnot both of \\`\\`WGDEVICE\\_A\\_IFINDEX\\`\\` and \\`\\`WGDEVICE\\_A\\_IFNAME\\`\\`\\.\n\nIt is possible that the amount of configuration data exceeds that of the\nmaximum message length accepted by the kernel\\. In that case, several\nmessages should be sent one after another, with each successive one\nfilling in information not contained in the prior\\. Note that if\n\\`\\`WGDEVICE\\_F\\_REPLACE\\_PEERS\\`\\` is specified in the first message, it\nprobably should not be specified in fragments that come after, so that\nthe list of peers is only cleared the first time but appended after\\.\nLikewise for peers, if \\`\\`WGPEER\\_F\\_REPLACE\\_ALLOWEDIPS\\`\\` is specified in\nthe first message of a peer, it likely should not be specified in\nsubsequent fragments\\.\n\nIf an error occurs, \\`\\`NLMSG\\_ERROR\\`\\` will reply containing an errno\\.\n\nFlags: uns-admin-perm\nRequest attributes:\n- [.push_ifindex()](PushWgdevice::push_ifindex)\n- [.push_ifname()](PushWgdevice::push_ifname)\n- [.push_private_key()](PushWgdevice::push_private_key)\n- [.push_public_key()](PushWgdevice::push_public_key)\n- [.push_flags()](PushWgdevice::push_flags)\n- [.push_listen_port()](PushWgdevice::push_listen_port)\n- [.push_fwmark()](PushWgdevice::push_fwmark)\n- [.array_peers()](PushWgdevice::array_peers)\n"]
1845    pub fn op_set_device_do(self) -> OpSetDeviceDo<'buf> {
1846        let mut res = OpSetDeviceDo::new(self);
1847        res.request
1848            .do_writeback(res.protocol(), "op-set-device-do", OpSetDeviceDo::lookup);
1849        res
1850    }
1851}
1852#[cfg(test)]
1853mod generated_tests {
1854    use super::*;
1855    #[test]
1856    fn tests() {
1857        let _ = IterableWgdevice::get_flags;
1858        let _ = IterableWgdevice::get_fwmark;
1859        let _ = IterableWgdevice::get_ifindex;
1860        let _ = IterableWgdevice::get_ifname;
1861        let _ = IterableWgdevice::get_listen_port;
1862        let _ = IterableWgdevice::get_peers;
1863        let _ = IterableWgdevice::get_private_key;
1864        let _ = IterableWgdevice::get_public_key;
1865        let _ = PushWgdevice::<&mut Vec<u8>>::array_peers;
1866        let _ = PushWgdevice::<&mut Vec<u8>>::push_flags;
1867        let _ = PushWgdevice::<&mut Vec<u8>>::push_fwmark;
1868        let _ = PushWgdevice::<&mut Vec<u8>>::push_ifindex;
1869        let _ = PushWgdevice::<&mut Vec<u8>>::push_ifname;
1870        let _ = PushWgdevice::<&mut Vec<u8>>::push_listen_port;
1871        let _ = PushWgdevice::<&mut Vec<u8>>::push_private_key;
1872        let _ = PushWgdevice::<&mut Vec<u8>>::push_public_key;
1873    }
1874}