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\ngeneric netlink, with family `WG_GENL_NAME` and version\n`WG_GENL_VERSION`. It defines two commands: get and set. Note that while\nthey share many common attributes, these two commands actually accept a\nslightly different set of inputs and outputs. These differences are\nnoted under the individual attributes.\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.\n"]
67    pub sec: u64,
68    #[doc = "Number of nanoseconds, after the second began.\n"]
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.\n"]
145    PrivateKey(&'a [u8]),
146    PublicKey(&'a [u8]),
147    #[doc = "`0` or `WGDEVICE_F_REPLACE_PEERS` if all current peers should be removed\nprior to adding the list below.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
148    Flags(u32),
149    #[doc = "Set as `0` to choose randomly.\n"]
150    ListenPort(u16),
151    #[doc = "Set as `0` to disable.\n"]
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 Ok(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 Ok(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.\n"]
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 Ok(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 Ok(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 removed\nprior 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 Ok(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.\n"]
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 Ok(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.\n"]
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 Ok(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 Ok(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        let pos = self.pos;
318        self.pos = self.buf.len();
319        Some(Err(ErrorContext::new(
320            "Wgpeer",
321            None,
322            self.orig_loc,
323            self.buf.as_ptr().wrapping_add(pos) as usize,
324        )))
325    }
326}
327impl Wgdevice<'_> {
328    pub fn new<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
329        IterableWgdevice::with_loc(buf, buf.as_ptr() as usize)
330    }
331    fn attr_from_type(r#type: u16) -> Option<&'static str> {
332        let res = match r#type {
333            0u16 => "Unspec",
334            1u16 => "Ifindex",
335            2u16 => "Ifname",
336            3u16 => "PrivateKey",
337            4u16 => "PublicKey",
338            5u16 => "Flags",
339            6u16 => "ListenPort",
340            7u16 => "Fwmark",
341            8u16 => "Peers",
342            _ => return None,
343        };
344        Some(res)
345    }
346}
347#[derive(Clone, Copy, Default)]
348pub struct IterableWgdevice<'a> {
349    buf: &'a [u8],
350    pos: usize,
351    orig_loc: usize,
352}
353impl<'a> IterableWgdevice<'a> {
354    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
355        Self {
356            buf,
357            pos: 0,
358            orig_loc,
359        }
360    }
361    pub fn get_buf(&self) -> &'a [u8] {
362        self.buf
363    }
364}
365impl<'a> Iterator for IterableWgdevice<'a> {
366    type Item = Result<Wgdevice<'a>, ErrorContext>;
367    fn next(&mut self) -> Option<Self::Item> {
368        let mut pos;
369        let mut r#type;
370        loop {
371            pos = self.pos;
372            r#type = None;
373            if self.buf.len() == self.pos {
374                return None;
375            }
376            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
377                self.pos = self.buf.len();
378                break;
379            };
380            r#type = Some(header.r#type);
381            let res = match header.r#type {
382                1u16 => Wgdevice::Ifindex({
383                    let res = parse_u32(next);
384                    let Some(val) = res else { break };
385                    val
386                }),
387                2u16 => Wgdevice::Ifname({
388                    let res = CStr::from_bytes_with_nul(next).ok();
389                    let Some(val) = res else { break };
390                    val
391                }),
392                3u16 => Wgdevice::PrivateKey({
393                    let res = Some(next);
394                    let Some(val) = res else { break };
395                    val
396                }),
397                4u16 => Wgdevice::PublicKey({
398                    let res = Some(next);
399                    let Some(val) = res else { break };
400                    val
401                }),
402                5u16 => Wgdevice::Flags({
403                    let res = parse_u32(next);
404                    let Some(val) = res else { break };
405                    val
406                }),
407                6u16 => Wgdevice::ListenPort({
408                    let res = parse_u16(next);
409                    let Some(val) = res else { break };
410                    val
411                }),
412                7u16 => Wgdevice::Fwmark({
413                    let res = parse_u32(next);
414                    let Some(val) = res else { break };
415                    val
416                }),
417                8u16 => Wgdevice::Peers({
418                    let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
419                    let Some(val) = res else { break };
420                    val
421                }),
422                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
423                n => continue,
424            };
425            return Some(Ok(res));
426        }
427        Some(Err(ErrorContext::new(
428            "Wgdevice",
429            r#type.and_then(|t| Wgdevice::attr_from_type(t)),
430            self.orig_loc,
431            self.buf.as_ptr().wrapping_add(pos) as usize,
432        )))
433    }
434}
435impl std::fmt::Debug for IterableArrayWgpeer<'_> {
436    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
437        fmt.debug_list()
438            .entries(self.clone().map(FlattenErrorContext))
439            .finish()
440    }
441}
442impl<'a> std::fmt::Debug for IterableWgdevice<'_> {
443    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
444        let mut fmt = f.debug_struct("Wgdevice");
445        for attr in self.clone() {
446            let attr = match attr {
447                Ok(a) => a,
448                Err(err) => {
449                    fmt.finish()?;
450                    f.write_str("Err(")?;
451                    err.fmt(f)?;
452                    return f.write_str(")");
453                }
454            };
455            match attr {
456                Wgdevice::Ifindex(val) => fmt.field("Ifindex", &val),
457                Wgdevice::Ifname(val) => fmt.field("Ifname", &val),
458                Wgdevice::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
459                Wgdevice::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
460                Wgdevice::Flags(val) => {
461                    fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
462                }
463                Wgdevice::ListenPort(val) => fmt.field("ListenPort", &val),
464                Wgdevice::Fwmark(val) => fmt.field("Fwmark", &val),
465                Wgdevice::Peers(val) => fmt.field("Peers", &val),
466            };
467        }
468        fmt.finish()
469    }
470}
471impl IterableWgdevice<'_> {
472    pub fn lookup_attr(
473        &self,
474        offset: usize,
475        missing_type: Option<u16>,
476    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
477        let mut stack = Vec::new();
478        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
479        if missing_type.is_some() && cur == offset {
480            stack.push(("Wgdevice", offset));
481            return (
482                stack,
483                missing_type.and_then(|t| Wgdevice::attr_from_type(t)),
484            );
485        }
486        if cur > offset || cur + self.buf.len() < offset {
487            return (stack, None);
488        }
489        let mut attrs = self.clone();
490        let mut last_off = cur + attrs.pos;
491        let mut missing = None;
492        while let Some(attr) = attrs.next() {
493            let Ok(attr) = attr else { break };
494            match attr {
495                Wgdevice::Ifindex(val) => {
496                    if last_off == offset {
497                        stack.push(("Ifindex", last_off));
498                        break;
499                    }
500                }
501                Wgdevice::Ifname(val) => {
502                    if last_off == offset {
503                        stack.push(("Ifname", last_off));
504                        break;
505                    }
506                }
507                Wgdevice::PrivateKey(val) => {
508                    if last_off == offset {
509                        stack.push(("PrivateKey", last_off));
510                        break;
511                    }
512                }
513                Wgdevice::PublicKey(val) => {
514                    if last_off == offset {
515                        stack.push(("PublicKey", last_off));
516                        break;
517                    }
518                }
519                Wgdevice::Flags(val) => {
520                    if last_off == offset {
521                        stack.push(("Flags", last_off));
522                        break;
523                    }
524                }
525                Wgdevice::ListenPort(val) => {
526                    if last_off == offset {
527                        stack.push(("ListenPort", last_off));
528                        break;
529                    }
530                }
531                Wgdevice::Fwmark(val) => {
532                    if last_off == offset {
533                        stack.push(("Fwmark", last_off));
534                        break;
535                    }
536                }
537                Wgdevice::Peers(val) => {
538                    for entry in val {
539                        let Ok(attr) = entry else { break };
540                        (stack, missing) = attr.lookup_attr(offset, missing_type);
541                        if !stack.is_empty() {
542                            break;
543                        }
544                    }
545                    if !stack.is_empty() {
546                        stack.push(("Peers", last_off));
547                        break;
548                    }
549                }
550                _ => {}
551            };
552            last_off = cur + attrs.pos;
553        }
554        if !stack.is_empty() {
555            stack.push(("Wgdevice", cur));
556        }
557        (stack, missing)
558    }
559}
560#[derive(Clone)]
561pub enum Wgpeer<'a> {
562    PublicKey(&'a [u8]),
563    #[doc = "Set as all zeros to remove.\n"]
564    PresharedKey(&'a [u8]),
565    #[doc = "`0` and/or `WGPEER_F_REMOVE_ME` if the specified peer should not exist\nat the end of the operation, rather than added/updated and/or\n`WGPEER_F_REPLACE_ALLOWEDIPS` if all current allowed IPs of this peer\nshould 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)"]
566    Flags(u32),
567    #[doc = "struct sockaddr_in or struct sockaddr_in6\n"]
568    Endpoint(std::net::SocketAddr),
569    #[doc = "Set as `0` to disable.\n"]
570    PersistentKeepaliveInterval(u16),
571    LastHandshakeTime(KernelTimespec),
572    RxBytes(u64),
573    TxBytes(u64),
574    #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
575    Allowedips(IterableArrayWgallowedip<'a>),
576    #[doc = "Should not be set or used at all by most users of this API, as the most\nrecent protocol will be used when this is unset. Otherwise, must be set\nto `1`.\n"]
577    ProtocolVersion(u32),
578}
579impl<'a> IterableWgpeer<'a> {
580    pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
581        let mut iter = self.clone();
582        iter.pos = 0;
583        for attr in iter {
584            if let Ok(Wgpeer::PublicKey(val)) = attr {
585                return Ok(val);
586            }
587        }
588        Err(ErrorContext::new_missing(
589            "Wgpeer",
590            "PublicKey",
591            self.orig_loc,
592            self.buf.as_ptr() as usize,
593        ))
594    }
595    #[doc = "Set as all zeros to remove.\n"]
596    pub fn get_preshared_key(&self) -> Result<&'a [u8], ErrorContext> {
597        let mut iter = self.clone();
598        iter.pos = 0;
599        for attr in iter {
600            if let Ok(Wgpeer::PresharedKey(val)) = attr {
601                return Ok(val);
602            }
603        }
604        Err(ErrorContext::new_missing(
605            "Wgpeer",
606            "PresharedKey",
607            self.orig_loc,
608            self.buf.as_ptr() as usize,
609        ))
610    }
611    #[doc = "`0` and/or `WGPEER_F_REMOVE_ME` if the specified peer should not exist\nat the end of the operation, rather than added/updated and/or\n`WGPEER_F_REPLACE_ALLOWEDIPS` if all current allowed IPs of this peer\nshould 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)"]
612    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
613        let mut iter = self.clone();
614        iter.pos = 0;
615        for attr in iter {
616            if let Ok(Wgpeer::Flags(val)) = attr {
617                return Ok(val);
618            }
619        }
620        Err(ErrorContext::new_missing(
621            "Wgpeer",
622            "Flags",
623            self.orig_loc,
624            self.buf.as_ptr() as usize,
625        ))
626    }
627    #[doc = "struct sockaddr_in or struct sockaddr_in6\n"]
628    pub fn get_endpoint(&self) -> Result<std::net::SocketAddr, ErrorContext> {
629        let mut iter = self.clone();
630        iter.pos = 0;
631        for attr in iter {
632            if let Ok(Wgpeer::Endpoint(val)) = attr {
633                return Ok(val);
634            }
635        }
636        Err(ErrorContext::new_missing(
637            "Wgpeer",
638            "Endpoint",
639            self.orig_loc,
640            self.buf.as_ptr() as usize,
641        ))
642    }
643    #[doc = "Set as `0` to disable.\n"]
644    pub fn get_persistent_keepalive_interval(&self) -> Result<u16, ErrorContext> {
645        let mut iter = self.clone();
646        iter.pos = 0;
647        for attr in iter {
648            if let Ok(Wgpeer::PersistentKeepaliveInterval(val)) = attr {
649                return Ok(val);
650            }
651        }
652        Err(ErrorContext::new_missing(
653            "Wgpeer",
654            "PersistentKeepaliveInterval",
655            self.orig_loc,
656            self.buf.as_ptr() as usize,
657        ))
658    }
659    pub fn get_last_handshake_time(&self) -> Result<KernelTimespec, ErrorContext> {
660        let mut iter = self.clone();
661        iter.pos = 0;
662        for attr in iter {
663            if let Ok(Wgpeer::LastHandshakeTime(val)) = attr {
664                return Ok(val);
665            }
666        }
667        Err(ErrorContext::new_missing(
668            "Wgpeer",
669            "LastHandshakeTime",
670            self.orig_loc,
671            self.buf.as_ptr() as usize,
672        ))
673    }
674    pub fn get_rx_bytes(&self) -> Result<u64, ErrorContext> {
675        let mut iter = self.clone();
676        iter.pos = 0;
677        for attr in iter {
678            if let Ok(Wgpeer::RxBytes(val)) = attr {
679                return Ok(val);
680            }
681        }
682        Err(ErrorContext::new_missing(
683            "Wgpeer",
684            "RxBytes",
685            self.orig_loc,
686            self.buf.as_ptr() as usize,
687        ))
688    }
689    pub fn get_tx_bytes(&self) -> Result<u64, ErrorContext> {
690        let mut iter = self.clone();
691        iter.pos = 0;
692        for attr in iter {
693            if let Ok(Wgpeer::TxBytes(val)) = attr {
694                return Ok(val);
695            }
696        }
697        Err(ErrorContext::new_missing(
698            "Wgpeer",
699            "TxBytes",
700            self.orig_loc,
701            self.buf.as_ptr() as usize,
702        ))
703    }
704    #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
705    pub fn get_allowedips(
706        &self,
707    ) -> Result<ArrayIterable<IterableArrayWgallowedip<'a>, IterableWgallowedip<'a>>, ErrorContext>
708    {
709        for attr in self.clone() {
710            if let Ok(Wgpeer::Allowedips(val)) = attr {
711                return Ok(ArrayIterable::new(val));
712            }
713        }
714        Err(ErrorContext::new_missing(
715            "Wgpeer",
716            "Allowedips",
717            self.orig_loc,
718            self.buf.as_ptr() as usize,
719        ))
720    }
721    #[doc = "Should not be set or used at all by most users of this API, as the most\nrecent protocol will be used when this is unset. Otherwise, must be set\nto `1`.\n"]
722    pub fn get_protocol_version(&self) -> Result<u32, ErrorContext> {
723        let mut iter = self.clone();
724        iter.pos = 0;
725        for attr in iter {
726            if let Ok(Wgpeer::ProtocolVersion(val)) = attr {
727                return Ok(val);
728            }
729        }
730        Err(ErrorContext::new_missing(
731            "Wgpeer",
732            "ProtocolVersion",
733            self.orig_loc,
734            self.buf.as_ptr() as usize,
735        ))
736    }
737}
738impl Wgallowedip {
739    pub fn new_array(buf: &[u8]) -> IterableArrayWgallowedip<'_> {
740        IterableArrayWgallowedip::with_loc(buf, buf.as_ptr() as usize)
741    }
742}
743#[derive(Clone, Copy, Default)]
744pub struct IterableArrayWgallowedip<'a> {
745    buf: &'a [u8],
746    pos: usize,
747    orig_loc: usize,
748}
749impl<'a> IterableArrayWgallowedip<'a> {
750    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
751        Self {
752            buf,
753            pos: 0,
754            orig_loc,
755        }
756    }
757    pub fn get_buf(&self) -> &'a [u8] {
758        self.buf
759    }
760}
761impl<'a> Iterator for IterableArrayWgallowedip<'a> {
762    type Item = Result<IterableWgallowedip<'a>, ErrorContext>;
763    fn next(&mut self) -> Option<Self::Item> {
764        if self.buf.len() == self.pos {
765            return None;
766        }
767        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
768            {
769                return Some(Ok(IterableWgallowedip::with_loc(next, self.orig_loc)));
770            }
771        }
772        let pos = self.pos;
773        self.pos = self.buf.len();
774        Some(Err(ErrorContext::new(
775            "Wgallowedip",
776            None,
777            self.orig_loc,
778            self.buf.as_ptr().wrapping_add(pos) as usize,
779        )))
780    }
781}
782impl Wgpeer<'_> {
783    pub fn new<'a>(buf: &'a [u8]) -> IterableWgpeer<'a> {
784        IterableWgpeer::with_loc(buf, buf.as_ptr() as usize)
785    }
786    fn attr_from_type(r#type: u16) -> Option<&'static str> {
787        let res = match r#type {
788            0u16 => "Unspec",
789            1u16 => "PublicKey",
790            2u16 => "PresharedKey",
791            3u16 => "Flags",
792            4u16 => "Endpoint",
793            5u16 => "PersistentKeepaliveInterval",
794            6u16 => "LastHandshakeTime",
795            7u16 => "RxBytes",
796            8u16 => "TxBytes",
797            9u16 => "Allowedips",
798            10u16 => "ProtocolVersion",
799            _ => return None,
800        };
801        Some(res)
802    }
803}
804#[derive(Clone, Copy, Default)]
805pub struct IterableWgpeer<'a> {
806    buf: &'a [u8],
807    pos: usize,
808    orig_loc: usize,
809}
810impl<'a> IterableWgpeer<'a> {
811    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
812        Self {
813            buf,
814            pos: 0,
815            orig_loc,
816        }
817    }
818    pub fn get_buf(&self) -> &'a [u8] {
819        self.buf
820    }
821}
822impl<'a> Iterator for IterableWgpeer<'a> {
823    type Item = Result<Wgpeer<'a>, ErrorContext>;
824    fn next(&mut self) -> Option<Self::Item> {
825        let mut pos;
826        let mut r#type;
827        loop {
828            pos = self.pos;
829            r#type = None;
830            if self.buf.len() == self.pos {
831                return None;
832            }
833            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
834                self.pos = self.buf.len();
835                break;
836            };
837            r#type = Some(header.r#type);
838            let res = match header.r#type {
839                1u16 => Wgpeer::PublicKey({
840                    let res = Some(next);
841                    let Some(val) = res else { break };
842                    val
843                }),
844                2u16 => Wgpeer::PresharedKey({
845                    let res = Some(next);
846                    let Some(val) = res else { break };
847                    val
848                }),
849                3u16 => Wgpeer::Flags({
850                    let res = parse_u32(next);
851                    let Some(val) = res else { break };
852                    val
853                }),
854                4u16 => Wgpeer::Endpoint({
855                    let res = parse_sockaddr(next);
856                    let Some(val) = res else { break };
857                    val
858                }),
859                5u16 => Wgpeer::PersistentKeepaliveInterval({
860                    let res = parse_u16(next);
861                    let Some(val) = res else { break };
862                    val
863                }),
864                6u16 => Wgpeer::LastHandshakeTime({
865                    let res = Some(KernelTimespec::new_from_zeroed(next));
866                    let Some(val) = res else { break };
867                    val
868                }),
869                7u16 => Wgpeer::RxBytes({
870                    let res = parse_u64(next);
871                    let Some(val) = res else { break };
872                    val
873                }),
874                8u16 => Wgpeer::TxBytes({
875                    let res = parse_u64(next);
876                    let Some(val) = res else { break };
877                    val
878                }),
879                9u16 => Wgpeer::Allowedips({
880                    let res = Some(IterableArrayWgallowedip::with_loc(next, self.orig_loc));
881                    let Some(val) = res else { break };
882                    val
883                }),
884                10u16 => Wgpeer::ProtocolVersion({
885                    let res = parse_u32(next);
886                    let Some(val) = res else { break };
887                    val
888                }),
889                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
890                n => continue,
891            };
892            return Some(Ok(res));
893        }
894        Some(Err(ErrorContext::new(
895            "Wgpeer",
896            r#type.and_then(|t| Wgpeer::attr_from_type(t)),
897            self.orig_loc,
898            self.buf.as_ptr().wrapping_add(pos) as usize,
899        )))
900    }
901}
902impl std::fmt::Debug for IterableArrayWgallowedip<'_> {
903    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
904        fmt.debug_list()
905            .entries(self.clone().map(FlattenErrorContext))
906            .finish()
907    }
908}
909impl<'a> std::fmt::Debug for IterableWgpeer<'_> {
910    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
911        let mut fmt = f.debug_struct("Wgpeer");
912        for attr in self.clone() {
913            let attr = match attr {
914                Ok(a) => a,
915                Err(err) => {
916                    fmt.finish()?;
917                    f.write_str("Err(")?;
918                    err.fmt(f)?;
919                    return f.write_str(")");
920                }
921            };
922            match attr {
923                Wgpeer::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
924                Wgpeer::PresharedKey(val) => fmt.field("PresharedKey", &FormatHex(val)),
925                Wgpeer::Flags(val) => {
926                    fmt.field("Flags", &FormatFlags(val.into(), WgpeerFlags::from_value))
927                }
928                Wgpeer::Endpoint(val) => fmt.field("Endpoint", &val),
929                Wgpeer::PersistentKeepaliveInterval(val) => {
930                    fmt.field("PersistentKeepaliveInterval", &val)
931                }
932                Wgpeer::LastHandshakeTime(val) => fmt.field("LastHandshakeTime", &val),
933                Wgpeer::RxBytes(val) => fmt.field("RxBytes", &val),
934                Wgpeer::TxBytes(val) => fmt.field("TxBytes", &val),
935                Wgpeer::Allowedips(val) => fmt.field("Allowedips", &val),
936                Wgpeer::ProtocolVersion(val) => fmt.field("ProtocolVersion", &val),
937            };
938        }
939        fmt.finish()
940    }
941}
942impl IterableWgpeer<'_> {
943    pub fn lookup_attr(
944        &self,
945        offset: usize,
946        missing_type: Option<u16>,
947    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
948        let mut stack = Vec::new();
949        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
950        if missing_type.is_some() && cur == offset {
951            stack.push(("Wgpeer", offset));
952            return (stack, missing_type.and_then(|t| Wgpeer::attr_from_type(t)));
953        }
954        if cur > offset || cur + self.buf.len() < offset {
955            return (stack, None);
956        }
957        let mut attrs = self.clone();
958        let mut last_off = cur + attrs.pos;
959        let mut missing = None;
960        while let Some(attr) = attrs.next() {
961            let Ok(attr) = attr else { break };
962            match attr {
963                Wgpeer::PublicKey(val) => {
964                    if last_off == offset {
965                        stack.push(("PublicKey", last_off));
966                        break;
967                    }
968                }
969                Wgpeer::PresharedKey(val) => {
970                    if last_off == offset {
971                        stack.push(("PresharedKey", last_off));
972                        break;
973                    }
974                }
975                Wgpeer::Flags(val) => {
976                    if last_off == offset {
977                        stack.push(("Flags", last_off));
978                        break;
979                    }
980                }
981                Wgpeer::Endpoint(val) => {
982                    if last_off == offset {
983                        stack.push(("Endpoint", last_off));
984                        break;
985                    }
986                }
987                Wgpeer::PersistentKeepaliveInterval(val) => {
988                    if last_off == offset {
989                        stack.push(("PersistentKeepaliveInterval", last_off));
990                        break;
991                    }
992                }
993                Wgpeer::LastHandshakeTime(val) => {
994                    if last_off == offset {
995                        stack.push(("LastHandshakeTime", last_off));
996                        break;
997                    }
998                }
999                Wgpeer::RxBytes(val) => {
1000                    if last_off == offset {
1001                        stack.push(("RxBytes", last_off));
1002                        break;
1003                    }
1004                }
1005                Wgpeer::TxBytes(val) => {
1006                    if last_off == offset {
1007                        stack.push(("TxBytes", last_off));
1008                        break;
1009                    }
1010                }
1011                Wgpeer::Allowedips(val) => {
1012                    for entry in val {
1013                        let Ok(attr) = entry else { break };
1014                        (stack, missing) = attr.lookup_attr(offset, missing_type);
1015                        if !stack.is_empty() {
1016                            break;
1017                        }
1018                    }
1019                    if !stack.is_empty() {
1020                        stack.push(("Allowedips", last_off));
1021                        break;
1022                    }
1023                }
1024                Wgpeer::ProtocolVersion(val) => {
1025                    if last_off == offset {
1026                        stack.push(("ProtocolVersion", last_off));
1027                        break;
1028                    }
1029                }
1030                _ => {}
1031            };
1032            last_off = cur + attrs.pos;
1033        }
1034        if !stack.is_empty() {
1035            stack.push(("Wgpeer", cur));
1036        }
1037        (stack, missing)
1038    }
1039}
1040#[derive(Clone)]
1041pub enum Wgallowedip {
1042    #[doc = "IP family, either `AF_INET` or `AF_INET6`.\n"]
1043    Family(u16),
1044    #[doc = "Either `struct in_addr` or `struct in6_addr`.\n"]
1045    Ipaddr(std::net::IpAddr),
1046    CidrMask(u8),
1047    #[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)"]
1048    Flags(u32),
1049}
1050impl<'a> IterableWgallowedip<'a> {
1051    #[doc = "IP family, either `AF_INET` or `AF_INET6`.\n"]
1052    pub fn get_family(&self) -> Result<u16, ErrorContext> {
1053        let mut iter = self.clone();
1054        iter.pos = 0;
1055        for attr in iter {
1056            if let Ok(Wgallowedip::Family(val)) = attr {
1057                return Ok(val);
1058            }
1059        }
1060        Err(ErrorContext::new_missing(
1061            "Wgallowedip",
1062            "Family",
1063            self.orig_loc,
1064            self.buf.as_ptr() as usize,
1065        ))
1066    }
1067    #[doc = "Either `struct in_addr` or `struct in6_addr`.\n"]
1068    pub fn get_ipaddr(&self) -> Result<std::net::IpAddr, ErrorContext> {
1069        let mut iter = self.clone();
1070        iter.pos = 0;
1071        for attr in iter {
1072            if let Ok(Wgallowedip::Ipaddr(val)) = attr {
1073                return Ok(val);
1074            }
1075        }
1076        Err(ErrorContext::new_missing(
1077            "Wgallowedip",
1078            "Ipaddr",
1079            self.orig_loc,
1080            self.buf.as_ptr() as usize,
1081        ))
1082    }
1083    pub fn get_cidr_mask(&self) -> Result<u8, ErrorContext> {
1084        let mut iter = self.clone();
1085        iter.pos = 0;
1086        for attr in iter {
1087            if let Ok(Wgallowedip::CidrMask(val)) = attr {
1088                return Ok(val);
1089            }
1090        }
1091        Err(ErrorContext::new_missing(
1092            "Wgallowedip",
1093            "CidrMask",
1094            self.orig_loc,
1095            self.buf.as_ptr() as usize,
1096        ))
1097    }
1098    #[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)"]
1099    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
1100        let mut iter = self.clone();
1101        iter.pos = 0;
1102        for attr in iter {
1103            if let Ok(Wgallowedip::Flags(val)) = attr {
1104                return Ok(val);
1105            }
1106        }
1107        Err(ErrorContext::new_missing(
1108            "Wgallowedip",
1109            "Flags",
1110            self.orig_loc,
1111            self.buf.as_ptr() as usize,
1112        ))
1113    }
1114}
1115impl Wgallowedip {
1116    pub fn new<'a>(buf: &'a [u8]) -> IterableWgallowedip<'a> {
1117        IterableWgallowedip::with_loc(buf, buf.as_ptr() as usize)
1118    }
1119    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1120        let res = match r#type {
1121            0u16 => "Unspec",
1122            1u16 => "Family",
1123            2u16 => "Ipaddr",
1124            3u16 => "CidrMask",
1125            4u16 => "Flags",
1126            _ => return None,
1127        };
1128        Some(res)
1129    }
1130}
1131#[derive(Clone, Copy, Default)]
1132pub struct IterableWgallowedip<'a> {
1133    buf: &'a [u8],
1134    pos: usize,
1135    orig_loc: usize,
1136}
1137impl<'a> IterableWgallowedip<'a> {
1138    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1139        Self {
1140            buf,
1141            pos: 0,
1142            orig_loc,
1143        }
1144    }
1145    pub fn get_buf(&self) -> &'a [u8] {
1146        self.buf
1147    }
1148}
1149impl<'a> Iterator for IterableWgallowedip<'a> {
1150    type Item = Result<Wgallowedip, ErrorContext>;
1151    fn next(&mut self) -> Option<Self::Item> {
1152        let mut pos;
1153        let mut r#type;
1154        loop {
1155            pos = self.pos;
1156            r#type = None;
1157            if self.buf.len() == self.pos {
1158                return None;
1159            }
1160            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1161                self.pos = self.buf.len();
1162                break;
1163            };
1164            r#type = Some(header.r#type);
1165            let res = match header.r#type {
1166                1u16 => Wgallowedip::Family({
1167                    let res = parse_u16(next);
1168                    let Some(val) = res else { break };
1169                    val
1170                }),
1171                2u16 => Wgallowedip::Ipaddr({
1172                    let res = parse_ip(next);
1173                    let Some(val) = res else { break };
1174                    val
1175                }),
1176                3u16 => Wgallowedip::CidrMask({
1177                    let res = parse_u8(next);
1178                    let Some(val) = res else { break };
1179                    val
1180                }),
1181                4u16 => Wgallowedip::Flags({
1182                    let res = parse_u32(next);
1183                    let Some(val) = res else { break };
1184                    val
1185                }),
1186                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1187                n => continue,
1188            };
1189            return Some(Ok(res));
1190        }
1191        Some(Err(ErrorContext::new(
1192            "Wgallowedip",
1193            r#type.and_then(|t| Wgallowedip::attr_from_type(t)),
1194            self.orig_loc,
1195            self.buf.as_ptr().wrapping_add(pos) as usize,
1196        )))
1197    }
1198}
1199impl std::fmt::Debug for IterableWgallowedip<'_> {
1200    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1201        let mut fmt = f.debug_struct("Wgallowedip");
1202        for attr in self.clone() {
1203            let attr = match attr {
1204                Ok(a) => a,
1205                Err(err) => {
1206                    fmt.finish()?;
1207                    f.write_str("Err(")?;
1208                    err.fmt(f)?;
1209                    return f.write_str(")");
1210                }
1211            };
1212            match attr {
1213                Wgallowedip::Family(val) => fmt.field("Family", &val),
1214                Wgallowedip::Ipaddr(val) => fmt.field("Ipaddr", &val),
1215                Wgallowedip::CidrMask(val) => fmt.field("CidrMask", &val),
1216                Wgallowedip::Flags(val) => fmt.field(
1217                    "Flags",
1218                    &FormatFlags(val.into(), WgallowedipFlags::from_value),
1219                ),
1220            };
1221        }
1222        fmt.finish()
1223    }
1224}
1225impl IterableWgallowedip<'_> {
1226    pub fn lookup_attr(
1227        &self,
1228        offset: usize,
1229        missing_type: Option<u16>,
1230    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1231        let mut stack = Vec::new();
1232        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1233        if missing_type.is_some() && cur == offset {
1234            stack.push(("Wgallowedip", offset));
1235            return (
1236                stack,
1237                missing_type.and_then(|t| Wgallowedip::attr_from_type(t)),
1238            );
1239        }
1240        if cur > offset || cur + self.buf.len() < offset {
1241            return (stack, None);
1242        }
1243        let mut attrs = self.clone();
1244        let mut last_off = cur + attrs.pos;
1245        while let Some(attr) = attrs.next() {
1246            let Ok(attr) = attr else { break };
1247            match attr {
1248                Wgallowedip::Family(val) => {
1249                    if last_off == offset {
1250                        stack.push(("Family", last_off));
1251                        break;
1252                    }
1253                }
1254                Wgallowedip::Ipaddr(val) => {
1255                    if last_off == offset {
1256                        stack.push(("Ipaddr", last_off));
1257                        break;
1258                    }
1259                }
1260                Wgallowedip::CidrMask(val) => {
1261                    if last_off == offset {
1262                        stack.push(("CidrMask", last_off));
1263                        break;
1264                    }
1265                }
1266                Wgallowedip::Flags(val) => {
1267                    if last_off == offset {
1268                        stack.push(("Flags", last_off));
1269                        break;
1270                    }
1271                }
1272                _ => {}
1273            };
1274            last_off = cur + attrs.pos;
1275        }
1276        if !stack.is_empty() {
1277            stack.push(("Wgallowedip", cur));
1278        }
1279        (stack, None)
1280    }
1281}
1282pub struct PushWgdevice<Prev: Pusher> {
1283    pub(crate) prev: Option<Prev>,
1284    pub(crate) header_offset: Option<usize>,
1285}
1286impl<Prev: Pusher> Pusher for PushWgdevice<Prev> {
1287    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1288        self.prev.as_mut().unwrap().as_vec_mut()
1289    }
1290    fn as_vec(&self) -> &Vec<u8> {
1291        self.prev.as_ref().unwrap().as_vec()
1292    }
1293}
1294pub struct PushArrayWgpeer<Prev: Pusher> {
1295    pub(crate) prev: Option<Prev>,
1296    pub(crate) header_offset: Option<usize>,
1297    pub(crate) counter: u16,
1298}
1299impl<Prev: Pusher> Pusher for PushArrayWgpeer<Prev> {
1300    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1301        self.prev.as_mut().unwrap().as_vec_mut()
1302    }
1303    fn as_vec(&self) -> &Vec<u8> {
1304        self.prev.as_ref().unwrap().as_vec()
1305    }
1306}
1307impl<Prev: Pusher> PushArrayWgpeer<Prev> {
1308    pub fn new(prev: Prev) -> Self {
1309        Self {
1310            prev: Some(prev),
1311            header_offset: None,
1312            counter: 0,
1313        }
1314    }
1315    pub fn end_array(mut self) -> Prev {
1316        let mut prev = self.prev.take().unwrap();
1317        if let Some(header_offset) = &self.header_offset {
1318            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1319        }
1320        prev
1321    }
1322    pub fn entry_nested(mut self) -> PushWgpeer<Self> {
1323        let index = self.counter;
1324        self.counter += 1;
1325        let header_offset = push_nested_header(self.as_vec_mut(), index);
1326        PushWgpeer {
1327            prev: Some(self),
1328            header_offset: Some(header_offset),
1329        }
1330    }
1331}
1332impl<Prev: Pusher> Drop for PushArrayWgpeer<Prev> {
1333    fn drop(&mut self) {
1334        if let Some(prev) = &mut self.prev {
1335            if let Some(header_offset) = &self.header_offset {
1336                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1337            }
1338        }
1339    }
1340}
1341impl<Prev: Pusher> PushWgdevice<Prev> {
1342    pub fn new(prev: Prev) -> Self {
1343        Self {
1344            prev: Some(prev),
1345            header_offset: None,
1346        }
1347    }
1348    pub fn end_nested(mut self) -> Prev {
1349        let mut prev = self.prev.take().unwrap();
1350        if let Some(header_offset) = &self.header_offset {
1351            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1352        }
1353        prev
1354    }
1355    pub fn push_ifindex(mut self, value: u32) -> Self {
1356        push_header(self.as_vec_mut(), 1u16, 4 as u16);
1357        self.as_vec_mut().extend(value.to_ne_bytes());
1358        self
1359    }
1360    pub fn push_ifname(mut self, value: &CStr) -> Self {
1361        push_header(
1362            self.as_vec_mut(),
1363            2u16,
1364            value.to_bytes_with_nul().len() as u16,
1365        );
1366        self.as_vec_mut().extend(value.to_bytes_with_nul());
1367        self
1368    }
1369    pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
1370        push_header(self.as_vec_mut(), 2u16, (value.len() + 1) as u16);
1371        self.as_vec_mut().extend(value);
1372        self.as_vec_mut().push(0);
1373        self
1374    }
1375    #[doc = "Set to all zeros to remove.\n"]
1376    pub fn push_private_key(mut self, value: &[u8]) -> Self {
1377        push_header(self.as_vec_mut(), 3u16, value.len() as u16);
1378        self.as_vec_mut().extend(value);
1379        self
1380    }
1381    pub fn push_public_key(mut self, value: &[u8]) -> Self {
1382        push_header(self.as_vec_mut(), 4u16, value.len() as u16);
1383        self.as_vec_mut().extend(value);
1384        self
1385    }
1386    #[doc = "`0` or `WGDEVICE_F_REPLACE_PEERS` if all current peers should be removed\nprior to adding the list below.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
1387    pub fn push_flags(mut self, value: u32) -> Self {
1388        push_header(self.as_vec_mut(), 5u16, 4 as u16);
1389        self.as_vec_mut().extend(value.to_ne_bytes());
1390        self
1391    }
1392    #[doc = "Set as `0` to choose randomly.\n"]
1393    pub fn push_listen_port(mut self, value: u16) -> Self {
1394        push_header(self.as_vec_mut(), 6u16, 2 as u16);
1395        self.as_vec_mut().extend(value.to_ne_bytes());
1396        self
1397    }
1398    #[doc = "Set as `0` to disable.\n"]
1399    pub fn push_fwmark(mut self, value: u32) -> Self {
1400        push_header(self.as_vec_mut(), 7u16, 4 as u16);
1401        self.as_vec_mut().extend(value.to_ne_bytes());
1402        self
1403    }
1404    #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
1405    pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
1406        let header_offset = push_nested_header(self.as_vec_mut(), 8u16);
1407        PushArrayWgpeer {
1408            prev: Some(self),
1409            header_offset: Some(header_offset),
1410            counter: 0,
1411        }
1412    }
1413}
1414impl<Prev: Pusher> Drop for PushWgdevice<Prev> {
1415    fn drop(&mut self) {
1416        if let Some(prev) = &mut self.prev {
1417            if let Some(header_offset) = &self.header_offset {
1418                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1419            }
1420        }
1421    }
1422}
1423pub struct PushWgpeer<Prev: Pusher> {
1424    pub(crate) prev: Option<Prev>,
1425    pub(crate) header_offset: Option<usize>,
1426}
1427impl<Prev: Pusher> Pusher for PushWgpeer<Prev> {
1428    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1429        self.prev.as_mut().unwrap().as_vec_mut()
1430    }
1431    fn as_vec(&self) -> &Vec<u8> {
1432        self.prev.as_ref().unwrap().as_vec()
1433    }
1434}
1435pub struct PushArrayWgallowedip<Prev: Pusher> {
1436    pub(crate) prev: Option<Prev>,
1437    pub(crate) header_offset: Option<usize>,
1438    pub(crate) counter: u16,
1439}
1440impl<Prev: Pusher> Pusher for PushArrayWgallowedip<Prev> {
1441    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1442        self.prev.as_mut().unwrap().as_vec_mut()
1443    }
1444    fn as_vec(&self) -> &Vec<u8> {
1445        self.prev.as_ref().unwrap().as_vec()
1446    }
1447}
1448impl<Prev: Pusher> PushArrayWgallowedip<Prev> {
1449    pub fn new(prev: Prev) -> Self {
1450        Self {
1451            prev: Some(prev),
1452            header_offset: None,
1453            counter: 0,
1454        }
1455    }
1456    pub fn end_array(mut self) -> Prev {
1457        let mut prev = self.prev.take().unwrap();
1458        if let Some(header_offset) = &self.header_offset {
1459            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1460        }
1461        prev
1462    }
1463    pub fn entry_nested(mut self) -> PushWgallowedip<Self> {
1464        let index = self.counter;
1465        self.counter += 1;
1466        let header_offset = push_nested_header(self.as_vec_mut(), index);
1467        PushWgallowedip {
1468            prev: Some(self),
1469            header_offset: Some(header_offset),
1470        }
1471    }
1472}
1473impl<Prev: Pusher> Drop for PushArrayWgallowedip<Prev> {
1474    fn drop(&mut self) {
1475        if let Some(prev) = &mut self.prev {
1476            if let Some(header_offset) = &self.header_offset {
1477                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1478            }
1479        }
1480    }
1481}
1482impl<Prev: Pusher> PushWgpeer<Prev> {
1483    pub fn new(prev: Prev) -> Self {
1484        Self {
1485            prev: Some(prev),
1486            header_offset: None,
1487        }
1488    }
1489    pub fn end_nested(mut self) -> Prev {
1490        let mut prev = self.prev.take().unwrap();
1491        if let Some(header_offset) = &self.header_offset {
1492            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1493        }
1494        prev
1495    }
1496    pub fn push_public_key(mut self, value: &[u8]) -> Self {
1497        push_header(self.as_vec_mut(), 1u16, value.len() as u16);
1498        self.as_vec_mut().extend(value);
1499        self
1500    }
1501    #[doc = "Set as all zeros to remove.\n"]
1502    pub fn push_preshared_key(mut self, value: &[u8]) -> Self {
1503        push_header(self.as_vec_mut(), 2u16, value.len() as u16);
1504        self.as_vec_mut().extend(value);
1505        self
1506    }
1507    #[doc = "`0` and/or `WGPEER_F_REMOVE_ME` if the specified peer should not exist\nat the end of the operation, rather than added/updated and/or\n`WGPEER_F_REPLACE_ALLOWEDIPS` if all current allowed IPs of this peer\nshould 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)"]
1508    pub fn push_flags(mut self, value: u32) -> Self {
1509        push_header(self.as_vec_mut(), 3u16, 4 as u16);
1510        self.as_vec_mut().extend(value.to_ne_bytes());
1511        self
1512    }
1513    #[doc = "struct sockaddr_in or struct sockaddr_in6\n"]
1514    pub fn push_endpoint(mut self, value: std::net::SocketAddr) -> Self {
1515        push_header(self.as_vec_mut(), 4u16, {
1516            match &value {
1517                SocketAddr::V4(_) => 16,
1518                SocketAddr::V6(_) => 28,
1519            }
1520        } as u16);
1521        encode_sockaddr(self.as_vec_mut(), value);
1522        self
1523    }
1524    #[doc = "Set as `0` to disable.\n"]
1525    pub fn push_persistent_keepalive_interval(mut self, value: u16) -> Self {
1526        push_header(self.as_vec_mut(), 5u16, 2 as u16);
1527        self.as_vec_mut().extend(value.to_ne_bytes());
1528        self
1529    }
1530    pub fn push_last_handshake_time(mut self, value: KernelTimespec) -> Self {
1531        push_header(self.as_vec_mut(), 6u16, value.as_slice().len() as u16);
1532        self.as_vec_mut().extend(value.as_slice());
1533        self
1534    }
1535    pub fn push_rx_bytes(mut self, value: u64) -> Self {
1536        push_header(self.as_vec_mut(), 7u16, 8 as u16);
1537        self.as_vec_mut().extend(value.to_ne_bytes());
1538        self
1539    }
1540    pub fn push_tx_bytes(mut self, value: u64) -> Self {
1541        push_header(self.as_vec_mut(), 8u16, 8 as u16);
1542        self.as_vec_mut().extend(value.to_ne_bytes());
1543        self
1544    }
1545    #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
1546    pub fn array_allowedips(mut self) -> PushArrayWgallowedip<Self> {
1547        let header_offset = push_nested_header(self.as_vec_mut(), 9u16);
1548        PushArrayWgallowedip {
1549            prev: Some(self),
1550            header_offset: Some(header_offset),
1551            counter: 0,
1552        }
1553    }
1554    #[doc = "Should not be set or used at all by most users of this API, as the most\nrecent protocol will be used when this is unset. Otherwise, must be set\nto `1`.\n"]
1555    pub fn push_protocol_version(mut self, value: u32) -> Self {
1556        push_header(self.as_vec_mut(), 10u16, 4 as u16);
1557        self.as_vec_mut().extend(value.to_ne_bytes());
1558        self
1559    }
1560}
1561impl<Prev: Pusher> Drop for PushWgpeer<Prev> {
1562    fn drop(&mut self) {
1563        if let Some(prev) = &mut self.prev {
1564            if let Some(header_offset) = &self.header_offset {
1565                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1566            }
1567        }
1568    }
1569}
1570pub struct PushWgallowedip<Prev: Pusher> {
1571    pub(crate) prev: Option<Prev>,
1572    pub(crate) header_offset: Option<usize>,
1573}
1574impl<Prev: Pusher> Pusher for PushWgallowedip<Prev> {
1575    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1576        self.prev.as_mut().unwrap().as_vec_mut()
1577    }
1578    fn as_vec(&self) -> &Vec<u8> {
1579        self.prev.as_ref().unwrap().as_vec()
1580    }
1581}
1582impl<Prev: Pusher> PushWgallowedip<Prev> {
1583    pub fn new(prev: Prev) -> Self {
1584        Self {
1585            prev: Some(prev),
1586            header_offset: None,
1587        }
1588    }
1589    pub fn end_nested(mut self) -> Prev {
1590        let mut prev = self.prev.take().unwrap();
1591        if let Some(header_offset) = &self.header_offset {
1592            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1593        }
1594        prev
1595    }
1596    #[doc = "IP family, either `AF_INET` or `AF_INET6`.\n"]
1597    pub fn push_family(mut self, value: u16) -> Self {
1598        push_header(self.as_vec_mut(), 1u16, 2 as u16);
1599        self.as_vec_mut().extend(value.to_ne_bytes());
1600        self
1601    }
1602    #[doc = "Either `struct in_addr` or `struct in6_addr`.\n"]
1603    pub fn push_ipaddr(mut self, value: std::net::IpAddr) -> Self {
1604        push_header(self.as_vec_mut(), 2u16, {
1605            match &value {
1606                IpAddr::V4(_) => 4,
1607                IpAddr::V6(_) => 16,
1608            }
1609        } as u16);
1610        encode_ip(self.as_vec_mut(), value);
1611        self
1612    }
1613    pub fn push_cidr_mask(mut self, value: u8) -> Self {
1614        push_header(self.as_vec_mut(), 3u16, 1 as u16);
1615        self.as_vec_mut().extend(value.to_ne_bytes());
1616        self
1617    }
1618    #[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)"]
1619    pub fn push_flags(mut self, value: u32) -> Self {
1620        push_header(self.as_vec_mut(), 4u16, 4 as u16);
1621        self.as_vec_mut().extend(value.to_ne_bytes());
1622        self
1623    }
1624}
1625impl<Prev: Pusher> Drop for PushWgallowedip<Prev> {
1626    fn drop(&mut self) {
1627        if let Some(prev) = &mut self.prev {
1628            if let Some(header_offset) = &self.header_offset {
1629                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1630            }
1631        }
1632    }
1633}
1634#[doc = "# Retrieve WireGuard device\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 several\ntimes in a row for the same peer. It is then up to the receiver to\ncoalesce 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 these\nmessages to form the complete list of peers.\n\nSince this is an `NLA_F_DUMP` command, the final message will always be\n`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\n\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\n"]
1635#[derive(Debug)]
1636pub struct OpGetDeviceDump<'r> {
1637    request: Request<'r>,
1638}
1639impl<'r> OpGetDeviceDump<'r> {
1640    pub fn new(mut request: Request<'r>) -> Self {
1641        Self::write_header(request.buf_mut());
1642        Self {
1643            request: request.set_dump(),
1644        }
1645    }
1646    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushWgdevice<&'buf mut Vec<u8>> {
1647        Self::write_header(buf);
1648        PushWgdevice::new(buf)
1649    }
1650    pub fn encode(&mut self) -> PushWgdevice<&mut Vec<u8>> {
1651        PushWgdevice::new(self.request.buf_mut())
1652    }
1653    pub fn into_encoder(self) -> PushWgdevice<RequestBuf<'r>> {
1654        PushWgdevice::new(self.request.buf)
1655    }
1656    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
1657        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1658        IterableWgdevice::with_loc(attrs, buf.as_ptr() as usize)
1659    }
1660    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1661        let mut header = BuiltinNfgenmsg::new();
1662        header.cmd = 0u8;
1663        header.version = 1u8;
1664        prev.as_vec_mut().extend(header.as_slice());
1665    }
1666}
1667impl NetlinkRequest for OpGetDeviceDump<'_> {
1668    fn protocol(&self) -> Protocol {
1669        Protocol::Generic("wireguard".as_bytes())
1670    }
1671    fn flags(&self) -> u16 {
1672        self.request.flags
1673    }
1674    fn payload(&self) -> &[u8] {
1675        self.request.buf()
1676    }
1677    type ReplyType<'buf> = IterableWgdevice<'buf>;
1678    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1679        Self::decode_request(buf)
1680    }
1681    fn lookup(
1682        buf: &[u8],
1683        offset: usize,
1684        missing_type: Option<u16>,
1685    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1686        Self::decode_request(buf).lookup_attr(offset, missing_type)
1687    }
1688}
1689#[doc = "# Set WireGuard device\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 the\nfirst message of a peer, it likely should not be specified in subsequent\nfragments.\n\nIf an error occurs, `NLMSG_ERROR` will reply containing an errno.\n\nFlags: uns-admin-perm\n\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\n"]
1690#[derive(Debug)]
1691pub struct OpSetDeviceDo<'r> {
1692    request: Request<'r>,
1693}
1694impl<'r> OpSetDeviceDo<'r> {
1695    pub fn new(mut request: Request<'r>) -> Self {
1696        Self::write_header(request.buf_mut());
1697        Self { request: request }
1698    }
1699    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushWgdevice<&'buf mut Vec<u8>> {
1700        Self::write_header(buf);
1701        PushWgdevice::new(buf)
1702    }
1703    pub fn encode(&mut self) -> PushWgdevice<&mut Vec<u8>> {
1704        PushWgdevice::new(self.request.buf_mut())
1705    }
1706    pub fn into_encoder(self) -> PushWgdevice<RequestBuf<'r>> {
1707        PushWgdevice::new(self.request.buf)
1708    }
1709    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
1710        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1711        IterableWgdevice::with_loc(attrs, buf.as_ptr() as usize)
1712    }
1713    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1714        let mut header = BuiltinNfgenmsg::new();
1715        header.cmd = 1u8;
1716        header.version = 1u8;
1717        prev.as_vec_mut().extend(header.as_slice());
1718    }
1719}
1720impl NetlinkRequest for OpSetDeviceDo<'_> {
1721    fn protocol(&self) -> Protocol {
1722        Protocol::Generic("wireguard".as_bytes())
1723    }
1724    fn flags(&self) -> u16 {
1725        self.request.flags
1726    }
1727    fn payload(&self) -> &[u8] {
1728        self.request.buf()
1729    }
1730    type ReplyType<'buf> = IterableWgdevice<'buf>;
1731    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1732        Self::decode_request(buf)
1733    }
1734    fn lookup(
1735        buf: &[u8],
1736        offset: usize,
1737        missing_type: Option<u16>,
1738    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1739        Self::decode_request(buf).lookup_attr(offset, missing_type)
1740    }
1741}
1742use crate::traits::LookupFn;
1743use crate::utils::RequestBuf;
1744#[derive(Debug)]
1745pub struct Request<'buf> {
1746    buf: RequestBuf<'buf>,
1747    flags: u16,
1748    writeback: Option<&'buf mut Option<RequestInfo>>,
1749}
1750#[allow(unused)]
1751#[derive(Debug, Clone)]
1752pub struct RequestInfo {
1753    protocol: Protocol,
1754    flags: u16,
1755    name: &'static str,
1756    lookup: LookupFn,
1757}
1758impl Request<'static> {
1759    pub fn new() -> Self {
1760        Self::new_from_buf(Vec::new())
1761    }
1762    pub fn new_from_buf(buf: Vec<u8>) -> Self {
1763        Self {
1764            flags: 0,
1765            buf: RequestBuf::Own(buf),
1766            writeback: None,
1767        }
1768    }
1769    pub fn into_buf(self) -> Vec<u8> {
1770        match self.buf {
1771            RequestBuf::Own(buf) => buf,
1772            _ => unreachable!(),
1773        }
1774    }
1775}
1776impl<'buf> Request<'buf> {
1777    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1778        buf.clear();
1779        Self::new_extend(buf)
1780    }
1781    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1782        Self {
1783            flags: 0,
1784            buf: RequestBuf::Ref(buf),
1785            writeback: None,
1786        }
1787    }
1788    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1789        let Some(writeback) = &mut self.writeback else {
1790            return;
1791        };
1792        **writeback = Some(RequestInfo {
1793            protocol,
1794            flags: self.flags,
1795            name,
1796            lookup,
1797        })
1798    }
1799    pub fn buf(&self) -> &Vec<u8> {
1800        self.buf.buf()
1801    }
1802    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1803        self.buf.buf_mut()
1804    }
1805    #[doc = "Set `NLM_F_CREATE` flag"]
1806    pub fn set_create(mut self) -> Self {
1807        self.flags |= consts::NLM_F_CREATE as u16;
1808        self
1809    }
1810    #[doc = "Set `NLM_F_EXCL` flag"]
1811    pub fn set_excl(mut self) -> Self {
1812        self.flags |= consts::NLM_F_EXCL as u16;
1813        self
1814    }
1815    #[doc = "Set `NLM_F_REPLACE` flag"]
1816    pub fn set_replace(mut self) -> Self {
1817        self.flags |= consts::NLM_F_REPLACE as u16;
1818        self
1819    }
1820    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1821    pub fn set_change(self) -> Self {
1822        self.set_create().set_replace()
1823    }
1824    #[doc = "Set `NLM_F_APPEND` flag"]
1825    pub fn set_append(mut self) -> Self {
1826        self.flags |= consts::NLM_F_APPEND as u16;
1827        self
1828    }
1829    #[doc = "Set `self.flags |= flags`"]
1830    pub fn set_flags(mut self, flags: u16) -> Self {
1831        self.flags |= flags;
1832        self
1833    }
1834    #[doc = "Set `self.flags ^= self.flags & flags`"]
1835    pub fn unset_flags(mut self, flags: u16) -> Self {
1836        self.flags ^= self.flags & flags;
1837        self
1838    }
1839    #[doc = "Set `NLM_F_DUMP` flag"]
1840    fn set_dump(mut self) -> Self {
1841        self.flags |= consts::NLM_F_DUMP as u16;
1842        self
1843    }
1844    #[doc = "# Retrieve WireGuard device\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 several\ntimes in a row for the same peer. It is then up to the receiver to\ncoalesce 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 these\nmessages to form the complete list of peers.\n\nSince this is an `NLA_F_DUMP` command, the final message will always be\n`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\n\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\n"]
1845    pub fn op_get_device_dump(self) -> OpGetDeviceDump<'buf> {
1846        let mut res = OpGetDeviceDump::new(self);
1847        res.request.do_writeback(
1848            res.protocol(),
1849            "op-get-device-dump",
1850            OpGetDeviceDump::lookup,
1851        );
1852        res
1853    }
1854    #[doc = "# Set WireGuard device\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 the\nfirst message of a peer, it likely should not be specified in subsequent\nfragments.\n\nIf an error occurs, `NLMSG_ERROR` will reply containing an errno.\n\nFlags: uns-admin-perm\n\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\n"]
1855    pub fn op_set_device_do(self) -> OpSetDeviceDo<'buf> {
1856        let mut res = OpSetDeviceDo::new(self);
1857        res.request
1858            .do_writeback(res.protocol(), "op-set-device-do", OpSetDeviceDo::lookup);
1859        res
1860    }
1861}
1862#[cfg(test)]
1863mod generated_tests {
1864    use super::*;
1865    #[test]
1866    fn tests() {
1867        let _ = IterableWgdevice::get_flags;
1868        let _ = IterableWgdevice::get_fwmark;
1869        let _ = IterableWgdevice::get_ifindex;
1870        let _ = IterableWgdevice::get_ifname;
1871        let _ = IterableWgdevice::get_listen_port;
1872        let _ = IterableWgdevice::get_peers;
1873        let _ = IterableWgdevice::get_private_key;
1874        let _ = IterableWgdevice::get_public_key;
1875        let _ = PushWgdevice::<&mut Vec<u8>>::array_peers;
1876        let _ = PushWgdevice::<&mut Vec<u8>>::push_flags;
1877        let _ = PushWgdevice::<&mut Vec<u8>>::push_fwmark;
1878        let _ = PushWgdevice::<&mut Vec<u8>>::push_ifindex;
1879        let _ = PushWgdevice::<&mut Vec<u8>>::push_ifname;
1880        let _ = PushWgdevice::<&mut Vec<u8>>::push_listen_port;
1881        let _ = PushWgdevice::<&mut Vec<u8>>::push_private_key;
1882        let _ = PushWgdevice::<&mut Vec<u8>>::push_public_key;
1883    }
1884}