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 defines two\ncommands: get and set. Note that while they share many common attributes,\nthese two commands actually accept a slightly different set of inputs and\noutputs. These differences are noted 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::{PushBuiltinBitfield32, PushBuiltinNfgenmsg, PushDummy, PushNlmsghdr};
13use crate::{
14    consts,
15    traits::{NetlinkRequest, Protocol},
16    utils::*,
17};
18pub const PROTONAME: &CStr = c"wireguard";
19pub const KEY_LEN: u64 = 32u64;
20#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
21#[derive(Debug, Clone, Copy)]
22pub enum WgdeviceFlags {
23    ReplacePeers = 1 << 0,
24}
25impl WgdeviceFlags {
26    pub fn from_value(value: u64) -> Option<Self> {
27        Some(match value {
28            n if n == 1 << 0 => Self::ReplacePeers,
29            _ => return None,
30        })
31    }
32}
33#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
34#[derive(Debug, Clone, Copy)]
35pub enum WgpeerFlags {
36    RemoveMe = 1 << 0,
37    ReplaceAllowedips = 1 << 1,
38    UpdateOnly = 1 << 2,
39}
40impl WgpeerFlags {
41    pub fn from_value(value: u64) -> Option<Self> {
42        Some(match value {
43            n if n == 1 << 0 => Self::RemoveMe,
44            n if n == 1 << 1 => Self::ReplaceAllowedips,
45            n if n == 1 << 2 => Self::UpdateOnly,
46            _ => return None,
47        })
48    }
49}
50#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
51#[derive(Debug, Clone, Copy)]
52pub enum WgallowedipFlags {
53    RemoveMe = 1 << 0,
54}
55impl WgallowedipFlags {
56    pub fn from_value(value: u64) -> Option<Self> {
57        Some(match value {
58            n if n == 1 << 0 => Self::RemoveMe,
59            _ => return None,
60        })
61    }
62}
63#[derive(Clone)]
64pub enum Wgdevice<'a> {
65    Ifindex(u32),
66    Ifname(&'a CStr),
67    #[doc = "Set to all zeros to remove."]
68    PrivateKey(&'a [u8]),
69    PublicKey(&'a [u8]),
70    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
71    Flags(u32),
72    #[doc = "Set as 0 to choose randomly."]
73    ListenPort(u16),
74    #[doc = "Set as 0 to disable."]
75    Fwmark(u32),
76    Peers(IterableArrayWgpeer<'a>),
77}
78impl<'a> IterableWgdevice<'a> {
79    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
80        let mut iter = self.clone();
81        iter.pos = 0;
82        for attr in iter {
83            if let Wgdevice::Ifindex(val) = attr? {
84                return Ok(val);
85            }
86        }
87        Err(ErrorContext::new_missing(
88            "Wgdevice",
89            "Ifindex",
90            self.orig_loc,
91            self.buf.as_ptr() as usize,
92        ))
93    }
94    pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
95        let mut iter = self.clone();
96        iter.pos = 0;
97        for attr in iter {
98            if let Wgdevice::Ifname(val) = attr? {
99                return Ok(val);
100            }
101        }
102        Err(ErrorContext::new_missing(
103            "Wgdevice",
104            "Ifname",
105            self.orig_loc,
106            self.buf.as_ptr() as usize,
107        ))
108    }
109    #[doc = "Set to all zeros to remove."]
110    pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
111        let mut iter = self.clone();
112        iter.pos = 0;
113        for attr in iter {
114            if let Wgdevice::PrivateKey(val) = attr? {
115                return Ok(val);
116            }
117        }
118        Err(ErrorContext::new_missing(
119            "Wgdevice",
120            "PrivateKey",
121            self.orig_loc,
122            self.buf.as_ptr() as usize,
123        ))
124    }
125    pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
126        let mut iter = self.clone();
127        iter.pos = 0;
128        for attr in iter {
129            if let Wgdevice::PublicKey(val) = attr? {
130                return Ok(val);
131            }
132        }
133        Err(ErrorContext::new_missing(
134            "Wgdevice",
135            "PublicKey",
136            self.orig_loc,
137            self.buf.as_ptr() as usize,
138        ))
139    }
140    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
141    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
142        let mut iter = self.clone();
143        iter.pos = 0;
144        for attr in iter {
145            if let Wgdevice::Flags(val) = attr? {
146                return Ok(val);
147            }
148        }
149        Err(ErrorContext::new_missing(
150            "Wgdevice",
151            "Flags",
152            self.orig_loc,
153            self.buf.as_ptr() as usize,
154        ))
155    }
156    #[doc = "Set as 0 to choose randomly."]
157    pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
158        let mut iter = self.clone();
159        iter.pos = 0;
160        for attr in iter {
161            if let Wgdevice::ListenPort(val) = attr? {
162                return Ok(val);
163            }
164        }
165        Err(ErrorContext::new_missing(
166            "Wgdevice",
167            "ListenPort",
168            self.orig_loc,
169            self.buf.as_ptr() as usize,
170        ))
171    }
172    #[doc = "Set as 0 to disable."]
173    pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
174        let mut iter = self.clone();
175        iter.pos = 0;
176        for attr in iter {
177            if let Wgdevice::Fwmark(val) = attr? {
178                return Ok(val);
179            }
180        }
181        Err(ErrorContext::new_missing(
182            "Wgdevice",
183            "Fwmark",
184            self.orig_loc,
185            self.buf.as_ptr() as usize,
186        ))
187    }
188    pub fn get_peers(
189        &self,
190    ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
191        for attr in self.clone() {
192            if let Wgdevice::Peers(val) = attr? {
193                return Ok(ArrayIterable::new(val));
194            }
195        }
196        Err(ErrorContext::new_missing(
197            "Wgdevice",
198            "Peers",
199            self.orig_loc,
200            self.buf.as_ptr() as usize,
201        ))
202    }
203}
204impl<'a> Wgpeer<'a> {
205    pub fn new_array(buf: &[u8]) -> IterableArrayWgpeer<'_> {
206        IterableArrayWgpeer::with_loc(buf, buf.as_ptr() as usize)
207    }
208}
209#[derive(Clone, Copy, Default)]
210pub struct IterableArrayWgpeer<'a> {
211    buf: &'a [u8],
212    pos: usize,
213    orig_loc: usize,
214}
215impl<'a> IterableArrayWgpeer<'a> {
216    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
217        Self {
218            buf,
219            pos: 0,
220            orig_loc,
221        }
222    }
223    pub fn get_buf(&self) -> &'a [u8] {
224        self.buf
225    }
226}
227impl<'a> Iterator for IterableArrayWgpeer<'a> {
228    type Item = Result<IterableWgpeer<'a>, ErrorContext>;
229    fn next(&mut self) -> Option<Self::Item> {
230        if self.buf.len() == self.pos {
231            return None;
232        }
233        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
234            {
235                return Some(Ok(IterableWgpeer::with_loc(next, self.orig_loc)));
236            }
237        }
238        Some(Err(ErrorContext::new(
239            "Wgpeer",
240            None,
241            self.orig_loc,
242            self.buf.as_ptr().wrapping_add(self.pos) as usize,
243        )))
244    }
245}
246impl<'a> Wgdevice<'a> {
247    pub fn new(buf: &'a [u8]) -> IterableWgdevice<'a> {
248        IterableWgdevice::with_loc(buf, buf.as_ptr() as usize)
249    }
250    fn attr_from_type(r#type: u16) -> Option<&'static str> {
251        let res = match r#type {
252            0u16 => "Unspec",
253            1u16 => "Ifindex",
254            2u16 => "Ifname",
255            3u16 => "PrivateKey",
256            4u16 => "PublicKey",
257            5u16 => "Flags",
258            6u16 => "ListenPort",
259            7u16 => "Fwmark",
260            8u16 => "Peers",
261            _ => return None,
262        };
263        Some(res)
264    }
265}
266#[derive(Clone, Copy, Default)]
267pub struct IterableWgdevice<'a> {
268    buf: &'a [u8],
269    pos: usize,
270    orig_loc: usize,
271}
272impl<'a> IterableWgdevice<'a> {
273    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
274        Self {
275            buf,
276            pos: 0,
277            orig_loc,
278        }
279    }
280    pub fn get_buf(&self) -> &'a [u8] {
281        self.buf
282    }
283}
284impl<'a> Iterator for IterableWgdevice<'a> {
285    type Item = Result<Wgdevice<'a>, ErrorContext>;
286    fn next(&mut self) -> Option<Self::Item> {
287        if self.buf.len() == self.pos {
288            return None;
289        }
290        let pos = self.pos;
291        let mut r#type = None;
292        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
293            r#type = Some(header.r#type);
294            let res = match header.r#type {
295                1u16 => Wgdevice::Ifindex({
296                    let res = parse_u32(next);
297                    let Some(val) = res else { break };
298                    val
299                }),
300                2u16 => Wgdevice::Ifname({
301                    let res = CStr::from_bytes_with_nul(next).ok();
302                    let Some(val) = res else { break };
303                    val
304                }),
305                3u16 => Wgdevice::PrivateKey({
306                    let res = Some(next);
307                    let Some(val) = res else { break };
308                    val
309                }),
310                4u16 => Wgdevice::PublicKey({
311                    let res = Some(next);
312                    let Some(val) = res else { break };
313                    val
314                }),
315                5u16 => Wgdevice::Flags({
316                    let res = parse_u32(next);
317                    let Some(val) = res else { break };
318                    val
319                }),
320                6u16 => Wgdevice::ListenPort({
321                    let res = parse_u16(next);
322                    let Some(val) = res else { break };
323                    val
324                }),
325                7u16 => Wgdevice::Fwmark({
326                    let res = parse_u32(next);
327                    let Some(val) = res else { break };
328                    val
329                }),
330                8u16 => Wgdevice::Peers({
331                    let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
332                    let Some(val) = res else { break };
333                    val
334                }),
335                n => {
336                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
337                        break;
338                    } else {
339                        continue;
340                    }
341                }
342            };
343            return Some(Ok(res));
344        }
345        Some(Err(ErrorContext::new(
346            "Wgdevice",
347            r#type.and_then(|t| Wgdevice::attr_from_type(t)),
348            self.orig_loc,
349            self.buf.as_ptr().wrapping_add(pos) as usize,
350        )))
351    }
352}
353impl std::fmt::Debug for IterableArrayWgpeer<'_> {
354    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
355        fmt.debug_list()
356            .entries(self.clone().map(FlattenErrorContext))
357            .finish()
358    }
359}
360impl<'a> std::fmt::Debug for IterableWgdevice<'_> {
361    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
362        let mut fmt = f.debug_struct("Wgdevice");
363        for attr in self.clone() {
364            let attr = match attr {
365                Ok(a) => a,
366                Err(err) => {
367                    fmt.finish()?;
368                    f.write_str("Err(")?;
369                    err.fmt(f)?;
370                    return f.write_str(")");
371                }
372            };
373            match attr {
374                Wgdevice::Ifindex(val) => fmt.field("Ifindex", &val),
375                Wgdevice::Ifname(val) => fmt.field("Ifname", &val),
376                Wgdevice::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
377                Wgdevice::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
378                Wgdevice::Flags(val) => {
379                    fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
380                }
381                Wgdevice::ListenPort(val) => fmt.field("ListenPort", &val),
382                Wgdevice::Fwmark(val) => fmt.field("Fwmark", &val),
383                Wgdevice::Peers(val) => fmt.field("Peers", &val),
384            };
385        }
386        fmt.finish()
387    }
388}
389impl IterableWgdevice<'_> {
390    pub fn lookup_attr(
391        &self,
392        offset: usize,
393        missing_type: Option<u16>,
394    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
395        let mut stack = Vec::new();
396        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
397        if cur == offset {
398            stack.push(("Wgdevice", offset));
399            return (
400                stack,
401                missing_type.and_then(|t| Wgdevice::attr_from_type(t)),
402            );
403        }
404        if cur > offset || cur + self.buf.len() < offset {
405            return (stack, None);
406        }
407        let mut attrs = self.clone();
408        let mut last_off = cur + attrs.pos;
409        let mut missing = None;
410        while let Some(attr) = attrs.next() {
411            let Ok(attr) = attr else { break };
412            match attr {
413                Wgdevice::Ifindex(val) => {
414                    if last_off == offset {
415                        stack.push(("Ifindex", last_off));
416                        break;
417                    }
418                }
419                Wgdevice::Ifname(val) => {
420                    if last_off == offset {
421                        stack.push(("Ifname", last_off));
422                        break;
423                    }
424                }
425                Wgdevice::PrivateKey(val) => {
426                    if last_off == offset {
427                        stack.push(("PrivateKey", last_off));
428                        break;
429                    }
430                }
431                Wgdevice::PublicKey(val) => {
432                    if last_off == offset {
433                        stack.push(("PublicKey", last_off));
434                        break;
435                    }
436                }
437                Wgdevice::Flags(val) => {
438                    if last_off == offset {
439                        stack.push(("Flags", last_off));
440                        break;
441                    }
442                }
443                Wgdevice::ListenPort(val) => {
444                    if last_off == offset {
445                        stack.push(("ListenPort", last_off));
446                        break;
447                    }
448                }
449                Wgdevice::Fwmark(val) => {
450                    if last_off == offset {
451                        stack.push(("Fwmark", last_off));
452                        break;
453                    }
454                }
455                Wgdevice::Peers(val) => {
456                    for entry in val {
457                        let Ok(attr) = entry else { break };
458                        (stack, missing) = attr.lookup_attr(offset, missing_type);
459                        if !stack.is_empty() {
460                            break;
461                        }
462                    }
463                    if !stack.is_empty() {
464                        stack.push(("Peers", last_off));
465                        break;
466                    }
467                }
468                _ => {}
469            };
470            last_off = cur + attrs.pos;
471        }
472        if !stack.is_empty() {
473            stack.push(("Wgdevice", cur));
474        }
475        (stack, missing)
476    }
477}
478#[derive(Clone)]
479pub enum Wgpeer<'a> {
480    PublicKey(&'a [u8]),
481    #[doc = "Set as all zeros to remove."]
482    PresharedKey(&'a [u8]),
483    #[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\nand/or WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed IPs\nof this peer should be removed prior to adding the list below\nand/or WGPEER_F_UPDATE_ONLY if the peer should only be set if\nit already exists.\n\nAssociated type: \"WgpeerFlags\" (enum)"]
484    Flags(u32),
485    #[doc = "struct sockaddr_in or struct sockaddr_in6"]
486    Endpoint(std::net::SocketAddr),
487    #[doc = "Set as 0 to disable."]
488    PersistentKeepaliveInterval(u16),
489    LastHandshakeTime(PushKernelTimespec),
490    RxBytes(u64),
491    TxBytes(u64),
492    Allowedips(IterableArrayWgallowedip<'a>),
493    #[doc = "should not be set or used at all by most users of this API,\nas the most recent protocol will be used when this is unset.\nOtherwise, must be set to 1.\n"]
494    ProtocolVersion(u32),
495}
496impl<'a> IterableWgpeer<'a> {
497    pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
498        let mut iter = self.clone();
499        iter.pos = 0;
500        for attr in iter {
501            if let Wgpeer::PublicKey(val) = attr? {
502                return Ok(val);
503            }
504        }
505        Err(ErrorContext::new_missing(
506            "Wgpeer",
507            "PublicKey",
508            self.orig_loc,
509            self.buf.as_ptr() as usize,
510        ))
511    }
512    #[doc = "Set as all zeros to remove."]
513    pub fn get_preshared_key(&self) -> Result<&'a [u8], ErrorContext> {
514        let mut iter = self.clone();
515        iter.pos = 0;
516        for attr in iter {
517            if let Wgpeer::PresharedKey(val) = attr? {
518                return Ok(val);
519            }
520        }
521        Err(ErrorContext::new_missing(
522            "Wgpeer",
523            "PresharedKey",
524            self.orig_loc,
525            self.buf.as_ptr() as usize,
526        ))
527    }
528    #[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\nand/or WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed IPs\nof this peer should be removed prior to adding the list below\nand/or WGPEER_F_UPDATE_ONLY if the peer should only be set if\nit already exists.\n\nAssociated type: \"WgpeerFlags\" (enum)"]
529    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
530        let mut iter = self.clone();
531        iter.pos = 0;
532        for attr in iter {
533            if let Wgpeer::Flags(val) = attr? {
534                return Ok(val);
535            }
536        }
537        Err(ErrorContext::new_missing(
538            "Wgpeer",
539            "Flags",
540            self.orig_loc,
541            self.buf.as_ptr() as usize,
542        ))
543    }
544    #[doc = "struct sockaddr_in or struct sockaddr_in6"]
545    pub fn get_endpoint(&self) -> Result<std::net::SocketAddr, ErrorContext> {
546        let mut iter = self.clone();
547        iter.pos = 0;
548        for attr in iter {
549            if let Wgpeer::Endpoint(val) = attr? {
550                return Ok(val);
551            }
552        }
553        Err(ErrorContext::new_missing(
554            "Wgpeer",
555            "Endpoint",
556            self.orig_loc,
557            self.buf.as_ptr() as usize,
558        ))
559    }
560    #[doc = "Set as 0 to disable."]
561    pub fn get_persistent_keepalive_interval(&self) -> Result<u16, ErrorContext> {
562        let mut iter = self.clone();
563        iter.pos = 0;
564        for attr in iter {
565            if let Wgpeer::PersistentKeepaliveInterval(val) = attr? {
566                return Ok(val);
567            }
568        }
569        Err(ErrorContext::new_missing(
570            "Wgpeer",
571            "PersistentKeepaliveInterval",
572            self.orig_loc,
573            self.buf.as_ptr() as usize,
574        ))
575    }
576    pub fn get_last_handshake_time(&self) -> Result<PushKernelTimespec, ErrorContext> {
577        let mut iter = self.clone();
578        iter.pos = 0;
579        for attr in iter {
580            if let Wgpeer::LastHandshakeTime(val) = attr? {
581                return Ok(val);
582            }
583        }
584        Err(ErrorContext::new_missing(
585            "Wgpeer",
586            "LastHandshakeTime",
587            self.orig_loc,
588            self.buf.as_ptr() as usize,
589        ))
590    }
591    pub fn get_rx_bytes(&self) -> Result<u64, ErrorContext> {
592        let mut iter = self.clone();
593        iter.pos = 0;
594        for attr in iter {
595            if let Wgpeer::RxBytes(val) = attr? {
596                return Ok(val);
597            }
598        }
599        Err(ErrorContext::new_missing(
600            "Wgpeer",
601            "RxBytes",
602            self.orig_loc,
603            self.buf.as_ptr() as usize,
604        ))
605    }
606    pub fn get_tx_bytes(&self) -> Result<u64, ErrorContext> {
607        let mut iter = self.clone();
608        iter.pos = 0;
609        for attr in iter {
610            if let Wgpeer::TxBytes(val) = attr? {
611                return Ok(val);
612            }
613        }
614        Err(ErrorContext::new_missing(
615            "Wgpeer",
616            "TxBytes",
617            self.orig_loc,
618            self.buf.as_ptr() as usize,
619        ))
620    }
621    pub fn get_allowedips(
622        &self,
623    ) -> Result<ArrayIterable<IterableArrayWgallowedip<'a>, IterableWgallowedip<'a>>, ErrorContext>
624    {
625        for attr in self.clone() {
626            if let Wgpeer::Allowedips(val) = attr? {
627                return Ok(ArrayIterable::new(val));
628            }
629        }
630        Err(ErrorContext::new_missing(
631            "Wgpeer",
632            "Allowedips",
633            self.orig_loc,
634            self.buf.as_ptr() as usize,
635        ))
636    }
637    #[doc = "should not be set or used at all by most users of this API,\nas the most recent protocol will be used when this is unset.\nOtherwise, must be set to 1.\n"]
638    pub fn get_protocol_version(&self) -> Result<u32, ErrorContext> {
639        let mut iter = self.clone();
640        iter.pos = 0;
641        for attr in iter {
642            if let Wgpeer::ProtocolVersion(val) = attr? {
643                return Ok(val);
644            }
645        }
646        Err(ErrorContext::new_missing(
647            "Wgpeer",
648            "ProtocolVersion",
649            self.orig_loc,
650            self.buf.as_ptr() as usize,
651        ))
652    }
653}
654impl Wgallowedip {
655    pub fn new_array(buf: &[u8]) -> IterableArrayWgallowedip<'_> {
656        IterableArrayWgallowedip::with_loc(buf, buf.as_ptr() as usize)
657    }
658}
659#[derive(Clone, Copy, Default)]
660pub struct IterableArrayWgallowedip<'a> {
661    buf: &'a [u8],
662    pos: usize,
663    orig_loc: usize,
664}
665impl<'a> IterableArrayWgallowedip<'a> {
666    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
667        Self {
668            buf,
669            pos: 0,
670            orig_loc,
671        }
672    }
673    pub fn get_buf(&self) -> &'a [u8] {
674        self.buf
675    }
676}
677impl<'a> Iterator for IterableArrayWgallowedip<'a> {
678    type Item = Result<IterableWgallowedip<'a>, ErrorContext>;
679    fn next(&mut self) -> Option<Self::Item> {
680        if self.buf.len() == self.pos {
681            return None;
682        }
683        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
684            {
685                return Some(Ok(IterableWgallowedip::with_loc(next, self.orig_loc)));
686            }
687        }
688        Some(Err(ErrorContext::new(
689            "Wgallowedip",
690            None,
691            self.orig_loc,
692            self.buf.as_ptr().wrapping_add(self.pos) as usize,
693        )))
694    }
695}
696impl<'a> Wgpeer<'a> {
697    pub fn new(buf: &'a [u8]) -> IterableWgpeer<'a> {
698        IterableWgpeer::with_loc(buf, buf.as_ptr() as usize)
699    }
700    fn attr_from_type(r#type: u16) -> Option<&'static str> {
701        let res = match r#type {
702            0u16 => "Unspec",
703            1u16 => "PublicKey",
704            2u16 => "PresharedKey",
705            3u16 => "Flags",
706            4u16 => "Endpoint",
707            5u16 => "PersistentKeepaliveInterval",
708            6u16 => "LastHandshakeTime",
709            7u16 => "RxBytes",
710            8u16 => "TxBytes",
711            9u16 => "Allowedips",
712            10u16 => "ProtocolVersion",
713            _ => return None,
714        };
715        Some(res)
716    }
717}
718#[derive(Clone, Copy, Default)]
719pub struct IterableWgpeer<'a> {
720    buf: &'a [u8],
721    pos: usize,
722    orig_loc: usize,
723}
724impl<'a> IterableWgpeer<'a> {
725    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
726        Self {
727            buf,
728            pos: 0,
729            orig_loc,
730        }
731    }
732    pub fn get_buf(&self) -> &'a [u8] {
733        self.buf
734    }
735}
736impl<'a> Iterator for IterableWgpeer<'a> {
737    type Item = Result<Wgpeer<'a>, ErrorContext>;
738    fn next(&mut self) -> Option<Self::Item> {
739        if self.buf.len() == self.pos {
740            return None;
741        }
742        let pos = self.pos;
743        let mut r#type = None;
744        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
745            r#type = Some(header.r#type);
746            let res = match header.r#type {
747                1u16 => Wgpeer::PublicKey({
748                    let res = Some(next);
749                    let Some(val) = res else { break };
750                    val
751                }),
752                2u16 => Wgpeer::PresharedKey({
753                    let res = Some(next);
754                    let Some(val) = res else { break };
755                    val
756                }),
757                3u16 => Wgpeer::Flags({
758                    let res = parse_u32(next);
759                    let Some(val) = res else { break };
760                    val
761                }),
762                4u16 => Wgpeer::Endpoint({
763                    let res = parse_sockaddr(next);
764                    let Some(val) = res else { break };
765                    val
766                }),
767                5u16 => Wgpeer::PersistentKeepaliveInterval({
768                    let res = parse_u16(next);
769                    let Some(val) = res else { break };
770                    val
771                }),
772                6u16 => Wgpeer::LastHandshakeTime({
773                    let res = PushKernelTimespec::new_from_slice(next);
774                    let Some(val) = res else { break };
775                    val
776                }),
777                7u16 => Wgpeer::RxBytes({
778                    let res = parse_u64(next);
779                    let Some(val) = res else { break };
780                    val
781                }),
782                8u16 => Wgpeer::TxBytes({
783                    let res = parse_u64(next);
784                    let Some(val) = res else { break };
785                    val
786                }),
787                9u16 => Wgpeer::Allowedips({
788                    let res = Some(IterableArrayWgallowedip::with_loc(next, self.orig_loc));
789                    let Some(val) = res else { break };
790                    val
791                }),
792                10u16 => Wgpeer::ProtocolVersion({
793                    let res = parse_u32(next);
794                    let Some(val) = res else { break };
795                    val
796                }),
797                n => {
798                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
799                        break;
800                    } else {
801                        continue;
802                    }
803                }
804            };
805            return Some(Ok(res));
806        }
807        Some(Err(ErrorContext::new(
808            "Wgpeer",
809            r#type.and_then(|t| Wgpeer::attr_from_type(t)),
810            self.orig_loc,
811            self.buf.as_ptr().wrapping_add(pos) as usize,
812        )))
813    }
814}
815impl std::fmt::Debug for IterableArrayWgallowedip<'_> {
816    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
817        fmt.debug_list()
818            .entries(self.clone().map(FlattenErrorContext))
819            .finish()
820    }
821}
822impl<'a> std::fmt::Debug for IterableWgpeer<'_> {
823    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
824        let mut fmt = f.debug_struct("Wgpeer");
825        for attr in self.clone() {
826            let attr = match attr {
827                Ok(a) => a,
828                Err(err) => {
829                    fmt.finish()?;
830                    f.write_str("Err(")?;
831                    err.fmt(f)?;
832                    return f.write_str(")");
833                }
834            };
835            match attr {
836                Wgpeer::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
837                Wgpeer::PresharedKey(val) => fmt.field("PresharedKey", &FormatHex(val)),
838                Wgpeer::Flags(val) => {
839                    fmt.field("Flags", &FormatFlags(val.into(), WgpeerFlags::from_value))
840                }
841                Wgpeer::Endpoint(val) => fmt.field("Endpoint", &val),
842                Wgpeer::PersistentKeepaliveInterval(val) => {
843                    fmt.field("PersistentKeepaliveInterval", &val)
844                }
845                Wgpeer::LastHandshakeTime(val) => fmt.field("LastHandshakeTime", &val),
846                Wgpeer::RxBytes(val) => fmt.field("RxBytes", &val),
847                Wgpeer::TxBytes(val) => fmt.field("TxBytes", &val),
848                Wgpeer::Allowedips(val) => fmt.field("Allowedips", &val),
849                Wgpeer::ProtocolVersion(val) => fmt.field("ProtocolVersion", &val),
850            };
851        }
852        fmt.finish()
853    }
854}
855impl IterableWgpeer<'_> {
856    pub fn lookup_attr(
857        &self,
858        offset: usize,
859        missing_type: Option<u16>,
860    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
861        let mut stack = Vec::new();
862        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
863        if cur == offset {
864            stack.push(("Wgpeer", offset));
865            return (stack, missing_type.and_then(|t| Wgpeer::attr_from_type(t)));
866        }
867        if cur > offset || cur + self.buf.len() < offset {
868            return (stack, None);
869        }
870        let mut attrs = self.clone();
871        let mut last_off = cur + attrs.pos;
872        let mut missing = None;
873        while let Some(attr) = attrs.next() {
874            let Ok(attr) = attr else { break };
875            match attr {
876                Wgpeer::PublicKey(val) => {
877                    if last_off == offset {
878                        stack.push(("PublicKey", last_off));
879                        break;
880                    }
881                }
882                Wgpeer::PresharedKey(val) => {
883                    if last_off == offset {
884                        stack.push(("PresharedKey", last_off));
885                        break;
886                    }
887                }
888                Wgpeer::Flags(val) => {
889                    if last_off == offset {
890                        stack.push(("Flags", last_off));
891                        break;
892                    }
893                }
894                Wgpeer::Endpoint(val) => {
895                    if last_off == offset {
896                        stack.push(("Endpoint", last_off));
897                        break;
898                    }
899                }
900                Wgpeer::PersistentKeepaliveInterval(val) => {
901                    if last_off == offset {
902                        stack.push(("PersistentKeepaliveInterval", last_off));
903                        break;
904                    }
905                }
906                Wgpeer::LastHandshakeTime(val) => {
907                    if last_off == offset {
908                        stack.push(("LastHandshakeTime", last_off));
909                        break;
910                    }
911                }
912                Wgpeer::RxBytes(val) => {
913                    if last_off == offset {
914                        stack.push(("RxBytes", last_off));
915                        break;
916                    }
917                }
918                Wgpeer::TxBytes(val) => {
919                    if last_off == offset {
920                        stack.push(("TxBytes", last_off));
921                        break;
922                    }
923                }
924                Wgpeer::Allowedips(val) => {
925                    for entry in val {
926                        let Ok(attr) = entry else { break };
927                        (stack, missing) = attr.lookup_attr(offset, missing_type);
928                        if !stack.is_empty() {
929                            break;
930                        }
931                    }
932                    if !stack.is_empty() {
933                        stack.push(("Allowedips", last_off));
934                        break;
935                    }
936                }
937                Wgpeer::ProtocolVersion(val) => {
938                    if last_off == offset {
939                        stack.push(("ProtocolVersion", last_off));
940                        break;
941                    }
942                }
943                _ => {}
944            };
945            last_off = cur + attrs.pos;
946        }
947        if !stack.is_empty() {
948            stack.push(("Wgpeer", cur));
949        }
950        (stack, missing)
951    }
952}
953#[derive(Clone)]
954pub enum Wgallowedip {
955    Family(u16),
956    #[doc = "struct in_addr or struct in6_add"]
957    Ipaddr(std::net::IpAddr),
958    CidrMask(u8),
959    #[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)"]
960    Flags(u32),
961}
962impl<'a> IterableWgallowedip<'a> {
963    pub fn get_family(&self) -> Result<u16, ErrorContext> {
964        let mut iter = self.clone();
965        iter.pos = 0;
966        for attr in iter {
967            if let Wgallowedip::Family(val) = attr? {
968                return Ok(val);
969            }
970        }
971        Err(ErrorContext::new_missing(
972            "Wgallowedip",
973            "Family",
974            self.orig_loc,
975            self.buf.as_ptr() as usize,
976        ))
977    }
978    #[doc = "struct in_addr or struct in6_add"]
979    pub fn get_ipaddr(&self) -> Result<std::net::IpAddr, ErrorContext> {
980        let mut iter = self.clone();
981        iter.pos = 0;
982        for attr in iter {
983            if let Wgallowedip::Ipaddr(val) = attr? {
984                return Ok(val);
985            }
986        }
987        Err(ErrorContext::new_missing(
988            "Wgallowedip",
989            "Ipaddr",
990            self.orig_loc,
991            self.buf.as_ptr() as usize,
992        ))
993    }
994    pub fn get_cidr_mask(&self) -> Result<u8, ErrorContext> {
995        let mut iter = self.clone();
996        iter.pos = 0;
997        for attr in iter {
998            if let Wgallowedip::CidrMask(val) = attr? {
999                return Ok(val);
1000            }
1001        }
1002        Err(ErrorContext::new_missing(
1003            "Wgallowedip",
1004            "CidrMask",
1005            self.orig_loc,
1006            self.buf.as_ptr() as usize,
1007        ))
1008    }
1009    #[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)"]
1010    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
1011        let mut iter = self.clone();
1012        iter.pos = 0;
1013        for attr in iter {
1014            if let Wgallowedip::Flags(val) = attr? {
1015                return Ok(val);
1016            }
1017        }
1018        Err(ErrorContext::new_missing(
1019            "Wgallowedip",
1020            "Flags",
1021            self.orig_loc,
1022            self.buf.as_ptr() as usize,
1023        ))
1024    }
1025}
1026impl Wgallowedip {
1027    pub fn new(buf: &'_ [u8]) -> IterableWgallowedip<'_> {
1028        IterableWgallowedip::with_loc(buf, buf.as_ptr() as usize)
1029    }
1030    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1031        let res = match r#type {
1032            0u16 => "Unspec",
1033            1u16 => "Family",
1034            2u16 => "Ipaddr",
1035            3u16 => "CidrMask",
1036            4u16 => "Flags",
1037            _ => return None,
1038        };
1039        Some(res)
1040    }
1041}
1042#[derive(Clone, Copy, Default)]
1043pub struct IterableWgallowedip<'a> {
1044    buf: &'a [u8],
1045    pos: usize,
1046    orig_loc: usize,
1047}
1048impl<'a> IterableWgallowedip<'a> {
1049    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1050        Self {
1051            buf,
1052            pos: 0,
1053            orig_loc,
1054        }
1055    }
1056    pub fn get_buf(&self) -> &'a [u8] {
1057        self.buf
1058    }
1059}
1060impl<'a> Iterator for IterableWgallowedip<'a> {
1061    type Item = Result<Wgallowedip, ErrorContext>;
1062    fn next(&mut self) -> Option<Self::Item> {
1063        if self.buf.len() == self.pos {
1064            return None;
1065        }
1066        let pos = self.pos;
1067        let mut r#type = None;
1068        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
1069            r#type = Some(header.r#type);
1070            let res = match header.r#type {
1071                1u16 => Wgallowedip::Family({
1072                    let res = parse_u16(next);
1073                    let Some(val) = res else { break };
1074                    val
1075                }),
1076                2u16 => Wgallowedip::Ipaddr({
1077                    let res = parse_ip(next);
1078                    let Some(val) = res else { break };
1079                    val
1080                }),
1081                3u16 => Wgallowedip::CidrMask({
1082                    let res = parse_u8(next);
1083                    let Some(val) = res else { break };
1084                    val
1085                }),
1086                4u16 => Wgallowedip::Flags({
1087                    let res = parse_u32(next);
1088                    let Some(val) = res else { break };
1089                    val
1090                }),
1091                n => {
1092                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
1093                        break;
1094                    } else {
1095                        continue;
1096                    }
1097                }
1098            };
1099            return Some(Ok(res));
1100        }
1101        Some(Err(ErrorContext::new(
1102            "Wgallowedip",
1103            r#type.and_then(|t| Wgallowedip::attr_from_type(t)),
1104            self.orig_loc,
1105            self.buf.as_ptr().wrapping_add(pos) as usize,
1106        )))
1107    }
1108}
1109impl std::fmt::Debug for IterableWgallowedip<'_> {
1110    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1111        let mut fmt = f.debug_struct("Wgallowedip");
1112        for attr in self.clone() {
1113            let attr = match attr {
1114                Ok(a) => a,
1115                Err(err) => {
1116                    fmt.finish()?;
1117                    f.write_str("Err(")?;
1118                    err.fmt(f)?;
1119                    return f.write_str(")");
1120                }
1121            };
1122            match attr {
1123                Wgallowedip::Family(val) => fmt.field("Family", &val),
1124                Wgallowedip::Ipaddr(val) => fmt.field("Ipaddr", &val),
1125                Wgallowedip::CidrMask(val) => fmt.field("CidrMask", &val),
1126                Wgallowedip::Flags(val) => fmt.field(
1127                    "Flags",
1128                    &FormatFlags(val.into(), WgallowedipFlags::from_value),
1129                ),
1130            };
1131        }
1132        fmt.finish()
1133    }
1134}
1135impl IterableWgallowedip<'_> {
1136    pub fn lookup_attr(
1137        &self,
1138        offset: usize,
1139        missing_type: Option<u16>,
1140    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1141        let mut stack = Vec::new();
1142        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1143        if cur == offset {
1144            stack.push(("Wgallowedip", offset));
1145            return (
1146                stack,
1147                missing_type.and_then(|t| Wgallowedip::attr_from_type(t)),
1148            );
1149        }
1150        if cur > offset || cur + self.buf.len() < offset {
1151            return (stack, None);
1152        }
1153        let mut attrs = self.clone();
1154        let mut last_off = cur + attrs.pos;
1155        while let Some(attr) = attrs.next() {
1156            let Ok(attr) = attr else { break };
1157            match attr {
1158                Wgallowedip::Family(val) => {
1159                    if last_off == offset {
1160                        stack.push(("Family", last_off));
1161                        break;
1162                    }
1163                }
1164                Wgallowedip::Ipaddr(val) => {
1165                    if last_off == offset {
1166                        stack.push(("Ipaddr", last_off));
1167                        break;
1168                    }
1169                }
1170                Wgallowedip::CidrMask(val) => {
1171                    if last_off == offset {
1172                        stack.push(("CidrMask", last_off));
1173                        break;
1174                    }
1175                }
1176                Wgallowedip::Flags(val) => {
1177                    if last_off == offset {
1178                        stack.push(("Flags", last_off));
1179                        break;
1180                    }
1181                }
1182                _ => {}
1183            };
1184            last_off = cur + attrs.pos;
1185        }
1186        if !stack.is_empty() {
1187            stack.push(("Wgallowedip", cur));
1188        }
1189        (stack, None)
1190    }
1191}
1192pub struct PushWgdevice<Prev: Rec> {
1193    pub(crate) prev: Option<Prev>,
1194    pub(crate) header_offset: Option<usize>,
1195}
1196impl<Prev: Rec> Rec for PushWgdevice<Prev> {
1197    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1198        self.prev.as_mut().unwrap().as_rec_mut()
1199    }
1200}
1201pub struct PushArrayWgpeer<Prev: Rec> {
1202    pub(crate) prev: Option<Prev>,
1203    pub(crate) header_offset: Option<usize>,
1204    pub(crate) counter: u16,
1205}
1206impl<Prev: Rec> Rec for PushArrayWgpeer<Prev> {
1207    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1208        self.prev.as_mut().unwrap().as_rec_mut()
1209    }
1210}
1211impl<Prev: Rec> PushArrayWgpeer<Prev> {
1212    pub fn new(prev: Prev) -> Self {
1213        Self {
1214            prev: Some(prev),
1215            header_offset: None,
1216            counter: 0,
1217        }
1218    }
1219    pub fn end_array(mut self) -> Prev {
1220        let mut prev = self.prev.take().unwrap();
1221        if let Some(header_offset) = &self.header_offset {
1222            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1223        }
1224        prev
1225    }
1226    pub fn entry_nested(mut self) -> PushWgpeer<Self> {
1227        let index = self.counter;
1228        self.counter += 1;
1229        let header_offset = push_nested_header(self.as_rec_mut(), index);
1230        PushWgpeer {
1231            prev: Some(self),
1232            header_offset: Some(header_offset),
1233        }
1234    }
1235}
1236impl<Prev: Rec> Drop for PushArrayWgpeer<Prev> {
1237    fn drop(&mut self) {
1238        if let Some(prev) = &mut self.prev {
1239            if let Some(header_offset) = &self.header_offset {
1240                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1241            }
1242        }
1243    }
1244}
1245impl<Prev: Rec> PushWgdevice<Prev> {
1246    pub fn new(prev: Prev) -> Self {
1247        Self {
1248            prev: Some(prev),
1249            header_offset: None,
1250        }
1251    }
1252    pub fn end_nested(mut self) -> Prev {
1253        let mut prev = self.prev.take().unwrap();
1254        if let Some(header_offset) = &self.header_offset {
1255            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1256        }
1257        prev
1258    }
1259    pub fn push_ifindex(mut self, value: u32) -> Self {
1260        push_header(self.as_rec_mut(), 1u16, 4 as u16);
1261        self.as_rec_mut().extend(value.to_ne_bytes());
1262        self
1263    }
1264    pub fn push_ifname(mut self, value: &CStr) -> Self {
1265        push_header(
1266            self.as_rec_mut(),
1267            2u16,
1268            value.to_bytes_with_nul().len() as u16,
1269        );
1270        self.as_rec_mut().extend(value.to_bytes_with_nul());
1271        self
1272    }
1273    pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
1274        push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
1275        self.as_rec_mut().extend(value);
1276        self.as_rec_mut().push(0);
1277        self
1278    }
1279    #[doc = "Set to all zeros to remove."]
1280    pub fn push_private_key(mut self, value: &[u8]) -> Self {
1281        push_header(self.as_rec_mut(), 3u16, value.len() as u16);
1282        self.as_rec_mut().extend(value);
1283        self
1284    }
1285    pub fn push_public_key(mut self, value: &[u8]) -> Self {
1286        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
1287        self.as_rec_mut().extend(value);
1288        self
1289    }
1290    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
1291    pub fn push_flags(mut self, value: u32) -> Self {
1292        push_header(self.as_rec_mut(), 5u16, 4 as u16);
1293        self.as_rec_mut().extend(value.to_ne_bytes());
1294        self
1295    }
1296    #[doc = "Set as 0 to choose randomly."]
1297    pub fn push_listen_port(mut self, value: u16) -> Self {
1298        push_header(self.as_rec_mut(), 6u16, 2 as u16);
1299        self.as_rec_mut().extend(value.to_ne_bytes());
1300        self
1301    }
1302    #[doc = "Set as 0 to disable."]
1303    pub fn push_fwmark(mut self, value: u32) -> Self {
1304        push_header(self.as_rec_mut(), 7u16, 4 as u16);
1305        self.as_rec_mut().extend(value.to_ne_bytes());
1306        self
1307    }
1308    pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
1309        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
1310        PushArrayWgpeer {
1311            prev: Some(self),
1312            header_offset: Some(header_offset),
1313            counter: 0,
1314        }
1315    }
1316}
1317impl<Prev: Rec> Drop for PushWgdevice<Prev> {
1318    fn drop(&mut self) {
1319        if let Some(prev) = &mut self.prev {
1320            if let Some(header_offset) = &self.header_offset {
1321                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1322            }
1323        }
1324    }
1325}
1326pub struct PushWgpeer<Prev: Rec> {
1327    pub(crate) prev: Option<Prev>,
1328    pub(crate) header_offset: Option<usize>,
1329}
1330impl<Prev: Rec> Rec for PushWgpeer<Prev> {
1331    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1332        self.prev.as_mut().unwrap().as_rec_mut()
1333    }
1334}
1335pub struct PushArrayWgallowedip<Prev: Rec> {
1336    pub(crate) prev: Option<Prev>,
1337    pub(crate) header_offset: Option<usize>,
1338    pub(crate) counter: u16,
1339}
1340impl<Prev: Rec> Rec for PushArrayWgallowedip<Prev> {
1341    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1342        self.prev.as_mut().unwrap().as_rec_mut()
1343    }
1344}
1345impl<Prev: Rec> PushArrayWgallowedip<Prev> {
1346    pub fn new(prev: Prev) -> Self {
1347        Self {
1348            prev: Some(prev),
1349            header_offset: None,
1350            counter: 0,
1351        }
1352    }
1353    pub fn end_array(mut self) -> Prev {
1354        let mut prev = self.prev.take().unwrap();
1355        if let Some(header_offset) = &self.header_offset {
1356            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1357        }
1358        prev
1359    }
1360    pub fn entry_nested(mut self) -> PushWgallowedip<Self> {
1361        let index = self.counter;
1362        self.counter += 1;
1363        let header_offset = push_nested_header(self.as_rec_mut(), index);
1364        PushWgallowedip {
1365            prev: Some(self),
1366            header_offset: Some(header_offset),
1367        }
1368    }
1369}
1370impl<Prev: Rec> Drop for PushArrayWgallowedip<Prev> {
1371    fn drop(&mut self) {
1372        if let Some(prev) = &mut self.prev {
1373            if let Some(header_offset) = &self.header_offset {
1374                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1375            }
1376        }
1377    }
1378}
1379impl<Prev: Rec> PushWgpeer<Prev> {
1380    pub fn new(prev: Prev) -> Self {
1381        Self {
1382            prev: Some(prev),
1383            header_offset: None,
1384        }
1385    }
1386    pub fn end_nested(mut self) -> Prev {
1387        let mut prev = self.prev.take().unwrap();
1388        if let Some(header_offset) = &self.header_offset {
1389            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1390        }
1391        prev
1392    }
1393    pub fn push_public_key(mut self, value: &[u8]) -> Self {
1394        push_header(self.as_rec_mut(), 1u16, value.len() as u16);
1395        self.as_rec_mut().extend(value);
1396        self
1397    }
1398    #[doc = "Set as all zeros to remove."]
1399    pub fn push_preshared_key(mut self, value: &[u8]) -> Self {
1400        push_header(self.as_rec_mut(), 2u16, value.len() as u16);
1401        self.as_rec_mut().extend(value);
1402        self
1403    }
1404    #[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\nand/or WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed IPs\nof this peer should be removed prior to adding the list below\nand/or WGPEER_F_UPDATE_ONLY if the peer should only be set if\nit already exists.\n\nAssociated type: \"WgpeerFlags\" (enum)"]
1405    pub fn push_flags(mut self, value: u32) -> Self {
1406        push_header(self.as_rec_mut(), 3u16, 4 as u16);
1407        self.as_rec_mut().extend(value.to_ne_bytes());
1408        self
1409    }
1410    #[doc = "struct sockaddr_in or struct sockaddr_in6"]
1411    pub fn push_endpoint(mut self, value: std::net::SocketAddr) -> Self {
1412        push_header(self.as_rec_mut(), 4u16, {
1413            match &value {
1414                SocketAddr::V4(_) => 16,
1415                SocketAddr::V6(_) => 28,
1416            }
1417        } as u16);
1418        encode_sockaddr(self.as_rec_mut(), value);
1419        self
1420    }
1421    #[doc = "Set as 0 to disable."]
1422    pub fn push_persistent_keepalive_interval(mut self, value: u16) -> Self {
1423        push_header(self.as_rec_mut(), 5u16, 2 as u16);
1424        self.as_rec_mut().extend(value.to_ne_bytes());
1425        self
1426    }
1427    pub fn push_last_handshake_time(mut self, value: PushKernelTimespec) -> Self {
1428        push_header(self.as_rec_mut(), 6u16, value.as_slice().len() as u16);
1429        self.as_rec_mut().extend(value.as_slice());
1430        self
1431    }
1432    pub fn push_rx_bytes(mut self, value: u64) -> Self {
1433        push_header(self.as_rec_mut(), 7u16, 8 as u16);
1434        self.as_rec_mut().extend(value.to_ne_bytes());
1435        self
1436    }
1437    pub fn push_tx_bytes(mut self, value: u64) -> Self {
1438        push_header(self.as_rec_mut(), 8u16, 8 as u16);
1439        self.as_rec_mut().extend(value.to_ne_bytes());
1440        self
1441    }
1442    pub fn array_allowedips(mut self) -> PushArrayWgallowedip<Self> {
1443        let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
1444        PushArrayWgallowedip {
1445            prev: Some(self),
1446            header_offset: Some(header_offset),
1447            counter: 0,
1448        }
1449    }
1450    #[doc = "should not be set or used at all by most users of this API,\nas the most recent protocol will be used when this is unset.\nOtherwise, must be set to 1.\n"]
1451    pub fn push_protocol_version(mut self, value: u32) -> Self {
1452        push_header(self.as_rec_mut(), 10u16, 4 as u16);
1453        self.as_rec_mut().extend(value.to_ne_bytes());
1454        self
1455    }
1456}
1457impl<Prev: Rec> Drop for PushWgpeer<Prev> {
1458    fn drop(&mut self) {
1459        if let Some(prev) = &mut self.prev {
1460            if let Some(header_offset) = &self.header_offset {
1461                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1462            }
1463        }
1464    }
1465}
1466pub struct PushWgallowedip<Prev: Rec> {
1467    pub(crate) prev: Option<Prev>,
1468    pub(crate) header_offset: Option<usize>,
1469}
1470impl<Prev: Rec> Rec for PushWgallowedip<Prev> {
1471    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1472        self.prev.as_mut().unwrap().as_rec_mut()
1473    }
1474}
1475impl<Prev: Rec> PushWgallowedip<Prev> {
1476    pub fn new(prev: Prev) -> Self {
1477        Self {
1478            prev: Some(prev),
1479            header_offset: None,
1480        }
1481    }
1482    pub fn end_nested(mut self) -> Prev {
1483        let mut prev = self.prev.take().unwrap();
1484        if let Some(header_offset) = &self.header_offset {
1485            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1486        }
1487        prev
1488    }
1489    pub fn push_family(mut self, value: u16) -> Self {
1490        push_header(self.as_rec_mut(), 1u16, 2 as u16);
1491        self.as_rec_mut().extend(value.to_ne_bytes());
1492        self
1493    }
1494    #[doc = "struct in_addr or struct in6_add"]
1495    pub fn push_ipaddr(mut self, value: std::net::IpAddr) -> Self {
1496        push_header(self.as_rec_mut(), 2u16, {
1497            match &value {
1498                IpAddr::V4(_) => 4,
1499                IpAddr::V6(_) => 16,
1500            }
1501        } as u16);
1502        encode_ip(self.as_rec_mut(), value);
1503        self
1504    }
1505    pub fn push_cidr_mask(mut self, value: u8) -> Self {
1506        push_header(self.as_rec_mut(), 3u16, 1 as u16);
1507        self.as_rec_mut().extend(value.to_ne_bytes());
1508        self
1509    }
1510    #[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)"]
1511    pub fn push_flags(mut self, value: u32) -> Self {
1512        push_header(self.as_rec_mut(), 4u16, 4 as u16);
1513        self.as_rec_mut().extend(value.to_ne_bytes());
1514        self
1515    }
1516}
1517impl<Prev: Rec> Drop for PushWgallowedip<Prev> {
1518    fn drop(&mut self) {
1519        if let Some(prev) = &mut self.prev {
1520            if let Some(header_offset) = &self.header_offset {
1521                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1522            }
1523        }
1524    }
1525}
1526#[derive(Clone)]
1527pub struct PushKernelTimespec {
1528    pub(crate) buf: [u8; 16usize],
1529}
1530#[doc = "Create zero-initialized struct"]
1531impl Default for PushKernelTimespec {
1532    fn default() -> Self {
1533        Self {
1534            buf: [0u8; 16usize],
1535        }
1536    }
1537}
1538impl PushKernelTimespec {
1539    #[doc = "Create zero-initialized struct"]
1540    pub fn new() -> Self {
1541        Default::default()
1542    }
1543    #[doc = "Copy from contents from other slice"]
1544    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
1545        if other.len() != Self::len() {
1546            return None;
1547        }
1548        let mut buf = [0u8; Self::len()];
1549        buf.clone_from_slice(other);
1550        Some(Self { buf })
1551    }
1552    pub fn as_slice(&self) -> &[u8] {
1553        &self.buf
1554    }
1555    pub fn as_mut_slice(&mut self) -> &mut [u8] {
1556        &mut self.buf
1557    }
1558    pub const fn len() -> usize {
1559        16usize
1560    }
1561    #[doc = "Number of seconds, since UNIX epoch."]
1562    pub fn sec(&self) -> u64 {
1563        parse_u64(&self.buf[0usize..8usize]).unwrap()
1564    }
1565    #[doc = "Number of seconds, since UNIX epoch."]
1566    pub fn set_sec(&mut self, value: u64) {
1567        self.buf[0usize..8usize].copy_from_slice(&value.to_ne_bytes())
1568    }
1569    #[doc = "Number of nanoseconds, after the second began."]
1570    pub fn nsec(&self) -> u64 {
1571        parse_u64(&self.buf[8usize..16usize]).unwrap()
1572    }
1573    #[doc = "Number of nanoseconds, after the second began."]
1574    pub fn set_nsec(&mut self, value: u64) {
1575        self.buf[8usize..16usize].copy_from_slice(&value.to_ne_bytes())
1576    }
1577}
1578impl std::fmt::Debug for PushKernelTimespec {
1579    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1580        fmt.debug_struct("KernelTimespec")
1581            .field("sec", &self.sec())
1582            .field("nsec", &self.nsec())
1583            .finish()
1584    }
1585}
1586#[doc = "Retrieve WireGuard device.\n\nThe command should be called with one but not both of:\n* WGDEVICE_A_IFINDEX\n* WGDEVICE_A_IFNAME\n\nThe kernel will then return several messages (NLM_F_MULTI).\nIt is possible that all of the allowed IPs of a single peer will not\nfit within a single netlink message. In that case, the same peer will\nbe written in the following message, except it will only contain\nWGPEER_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\nin following messages, except those will only contain\nWGDEVICE_A_IFNAME and WGDEVICE_A_PEERS. It is then up to the receiver\nto coalesce these messages to form the complete list of peers.\n\nSince this is an NLA_F_DUMP command, the final message will always be\nNLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message\ncontains an integer error code. It is either zero or a negative error\ncode corresponding to the errno.\n"]
1587pub struct PushOpGetDeviceDumpRequest<Prev: Rec> {
1588    pub(crate) prev: Option<Prev>,
1589    pub(crate) header_offset: Option<usize>,
1590}
1591impl<Prev: Rec> Rec for PushOpGetDeviceDumpRequest<Prev> {
1592    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1593        self.prev.as_mut().unwrap().as_rec_mut()
1594    }
1595}
1596impl<Prev: Rec> PushOpGetDeviceDumpRequest<Prev> {
1597    pub fn new(mut prev: Prev) -> Self {
1598        Self::write_header(&mut prev);
1599        Self::new_without_header(prev)
1600    }
1601    fn new_without_header(prev: Prev) -> Self {
1602        Self {
1603            prev: Some(prev),
1604            header_offset: None,
1605        }
1606    }
1607    fn write_header(prev: &mut Prev) {
1608        let mut header = PushBuiltinNfgenmsg::new();
1609        header.set_cmd(0u8);
1610        header.set_version(1u8);
1611        prev.as_rec_mut().extend(header.as_slice());
1612    }
1613    pub fn end_nested(mut self) -> Prev {
1614        let mut prev = self.prev.take().unwrap();
1615        if let Some(header_offset) = &self.header_offset {
1616            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1617        }
1618        prev
1619    }
1620    pub fn push_ifindex(mut self, value: u32) -> Self {
1621        push_header(self.as_rec_mut(), 1u16, 4 as u16);
1622        self.as_rec_mut().extend(value.to_ne_bytes());
1623        self
1624    }
1625    pub fn push_ifname(mut self, value: &CStr) -> Self {
1626        push_header(
1627            self.as_rec_mut(),
1628            2u16,
1629            value.to_bytes_with_nul().len() as u16,
1630        );
1631        self.as_rec_mut().extend(value.to_bytes_with_nul());
1632        self
1633    }
1634    pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
1635        push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
1636        self.as_rec_mut().extend(value);
1637        self.as_rec_mut().push(0);
1638        self
1639    }
1640    #[doc = "Set to all zeros to remove."]
1641    pub fn push_private_key(mut self, value: &[u8]) -> Self {
1642        push_header(self.as_rec_mut(), 3u16, value.len() as u16);
1643        self.as_rec_mut().extend(value);
1644        self
1645    }
1646    pub fn push_public_key(mut self, value: &[u8]) -> Self {
1647        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
1648        self.as_rec_mut().extend(value);
1649        self
1650    }
1651    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
1652    pub fn push_flags(mut self, value: u32) -> Self {
1653        push_header(self.as_rec_mut(), 5u16, 4 as u16);
1654        self.as_rec_mut().extend(value.to_ne_bytes());
1655        self
1656    }
1657    #[doc = "Set as 0 to choose randomly."]
1658    pub fn push_listen_port(mut self, value: u16) -> Self {
1659        push_header(self.as_rec_mut(), 6u16, 2 as u16);
1660        self.as_rec_mut().extend(value.to_ne_bytes());
1661        self
1662    }
1663    #[doc = "Set as 0 to disable."]
1664    pub fn push_fwmark(mut self, value: u32) -> Self {
1665        push_header(self.as_rec_mut(), 7u16, 4 as u16);
1666        self.as_rec_mut().extend(value.to_ne_bytes());
1667        self
1668    }
1669    pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
1670        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
1671        PushArrayWgpeer {
1672            prev: Some(self),
1673            header_offset: Some(header_offset),
1674            counter: 0,
1675        }
1676    }
1677}
1678impl<Prev: Rec> Drop for PushOpGetDeviceDumpRequest<Prev> {
1679    fn drop(&mut self) {
1680        if let Some(prev) = &mut self.prev {
1681            if let Some(header_offset) = &self.header_offset {
1682                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1683            }
1684        }
1685    }
1686}
1687#[doc = "Retrieve WireGuard device.\n\nThe command should be called with one but not both of:\n* WGDEVICE_A_IFINDEX\n* WGDEVICE_A_IFNAME\n\nThe kernel will then return several messages (NLM_F_MULTI).\nIt is possible that all of the allowed IPs of a single peer will not\nfit within a single netlink message. In that case, the same peer will\nbe written in the following message, except it will only contain\nWGPEER_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\nin following messages, except those will only contain\nWGDEVICE_A_IFNAME and WGDEVICE_A_PEERS. It is then up to the receiver\nto coalesce these messages to form the complete list of peers.\n\nSince this is an NLA_F_DUMP command, the final message will always be\nNLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message\ncontains an integer error code. It is either zero or a negative error\ncode corresponding to the errno.\n"]
1688#[derive(Clone)]
1689pub enum OpGetDeviceDumpRequest<'a> {
1690    Ifindex(u32),
1691    Ifname(&'a CStr),
1692    #[doc = "Set to all zeros to remove."]
1693    PrivateKey(&'a [u8]),
1694    PublicKey(&'a [u8]),
1695    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
1696    Flags(u32),
1697    #[doc = "Set as 0 to choose randomly."]
1698    ListenPort(u16),
1699    #[doc = "Set as 0 to disable."]
1700    Fwmark(u32),
1701    Peers(IterableArrayWgpeer<'a>),
1702}
1703impl<'a> IterableOpGetDeviceDumpRequest<'a> {
1704    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
1705        let mut iter = self.clone();
1706        iter.pos = 0;
1707        for attr in iter {
1708            if let OpGetDeviceDumpRequest::Ifindex(val) = attr? {
1709                return Ok(val);
1710            }
1711        }
1712        Err(ErrorContext::new_missing(
1713            "OpGetDeviceDumpRequest",
1714            "Ifindex",
1715            self.orig_loc,
1716            self.buf.as_ptr() as usize,
1717        ))
1718    }
1719    pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
1720        let mut iter = self.clone();
1721        iter.pos = 0;
1722        for attr in iter {
1723            if let OpGetDeviceDumpRequest::Ifname(val) = attr? {
1724                return Ok(val);
1725            }
1726        }
1727        Err(ErrorContext::new_missing(
1728            "OpGetDeviceDumpRequest",
1729            "Ifname",
1730            self.orig_loc,
1731            self.buf.as_ptr() as usize,
1732        ))
1733    }
1734    #[doc = "Set to all zeros to remove."]
1735    pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
1736        let mut iter = self.clone();
1737        iter.pos = 0;
1738        for attr in iter {
1739            if let OpGetDeviceDumpRequest::PrivateKey(val) = attr? {
1740                return Ok(val);
1741            }
1742        }
1743        Err(ErrorContext::new_missing(
1744            "OpGetDeviceDumpRequest",
1745            "PrivateKey",
1746            self.orig_loc,
1747            self.buf.as_ptr() as usize,
1748        ))
1749    }
1750    pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
1751        let mut iter = self.clone();
1752        iter.pos = 0;
1753        for attr in iter {
1754            if let OpGetDeviceDumpRequest::PublicKey(val) = attr? {
1755                return Ok(val);
1756            }
1757        }
1758        Err(ErrorContext::new_missing(
1759            "OpGetDeviceDumpRequest",
1760            "PublicKey",
1761            self.orig_loc,
1762            self.buf.as_ptr() as usize,
1763        ))
1764    }
1765    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
1766    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
1767        let mut iter = self.clone();
1768        iter.pos = 0;
1769        for attr in iter {
1770            if let OpGetDeviceDumpRequest::Flags(val) = attr? {
1771                return Ok(val);
1772            }
1773        }
1774        Err(ErrorContext::new_missing(
1775            "OpGetDeviceDumpRequest",
1776            "Flags",
1777            self.orig_loc,
1778            self.buf.as_ptr() as usize,
1779        ))
1780    }
1781    #[doc = "Set as 0 to choose randomly."]
1782    pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
1783        let mut iter = self.clone();
1784        iter.pos = 0;
1785        for attr in iter {
1786            if let OpGetDeviceDumpRequest::ListenPort(val) = attr? {
1787                return Ok(val);
1788            }
1789        }
1790        Err(ErrorContext::new_missing(
1791            "OpGetDeviceDumpRequest",
1792            "ListenPort",
1793            self.orig_loc,
1794            self.buf.as_ptr() as usize,
1795        ))
1796    }
1797    #[doc = "Set as 0 to disable."]
1798    pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
1799        let mut iter = self.clone();
1800        iter.pos = 0;
1801        for attr in iter {
1802            if let OpGetDeviceDumpRequest::Fwmark(val) = attr? {
1803                return Ok(val);
1804            }
1805        }
1806        Err(ErrorContext::new_missing(
1807            "OpGetDeviceDumpRequest",
1808            "Fwmark",
1809            self.orig_loc,
1810            self.buf.as_ptr() as usize,
1811        ))
1812    }
1813    pub fn get_peers(
1814        &self,
1815    ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
1816        for attr in self.clone() {
1817            if let OpGetDeviceDumpRequest::Peers(val) = attr? {
1818                return Ok(ArrayIterable::new(val));
1819            }
1820        }
1821        Err(ErrorContext::new_missing(
1822            "OpGetDeviceDumpRequest",
1823            "Peers",
1824            self.orig_loc,
1825            self.buf.as_ptr() as usize,
1826        ))
1827    }
1828}
1829impl<'a> OpGetDeviceDumpRequest<'a> {
1830    pub fn new(buf: &'a [u8]) -> IterableOpGetDeviceDumpRequest<'a> {
1831        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
1832        IterableOpGetDeviceDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
1833    }
1834    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1835        Wgdevice::attr_from_type(r#type)
1836    }
1837}
1838#[derive(Clone, Copy, Default)]
1839pub struct IterableOpGetDeviceDumpRequest<'a> {
1840    buf: &'a [u8],
1841    pos: usize,
1842    orig_loc: usize,
1843}
1844impl<'a> IterableOpGetDeviceDumpRequest<'a> {
1845    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1846        Self {
1847            buf,
1848            pos: 0,
1849            orig_loc,
1850        }
1851    }
1852    pub fn get_buf(&self) -> &'a [u8] {
1853        self.buf
1854    }
1855}
1856impl<'a> Iterator for IterableOpGetDeviceDumpRequest<'a> {
1857    type Item = Result<OpGetDeviceDumpRequest<'a>, ErrorContext>;
1858    fn next(&mut self) -> Option<Self::Item> {
1859        if self.buf.len() == self.pos {
1860            return None;
1861        }
1862        let pos = self.pos;
1863        let mut r#type = None;
1864        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
1865            r#type = Some(header.r#type);
1866            let res = match header.r#type {
1867                1u16 => OpGetDeviceDumpRequest::Ifindex({
1868                    let res = parse_u32(next);
1869                    let Some(val) = res else { break };
1870                    val
1871                }),
1872                2u16 => OpGetDeviceDumpRequest::Ifname({
1873                    let res = CStr::from_bytes_with_nul(next).ok();
1874                    let Some(val) = res else { break };
1875                    val
1876                }),
1877                3u16 => OpGetDeviceDumpRequest::PrivateKey({
1878                    let res = Some(next);
1879                    let Some(val) = res else { break };
1880                    val
1881                }),
1882                4u16 => OpGetDeviceDumpRequest::PublicKey({
1883                    let res = Some(next);
1884                    let Some(val) = res else { break };
1885                    val
1886                }),
1887                5u16 => OpGetDeviceDumpRequest::Flags({
1888                    let res = parse_u32(next);
1889                    let Some(val) = res else { break };
1890                    val
1891                }),
1892                6u16 => OpGetDeviceDumpRequest::ListenPort({
1893                    let res = parse_u16(next);
1894                    let Some(val) = res else { break };
1895                    val
1896                }),
1897                7u16 => OpGetDeviceDumpRequest::Fwmark({
1898                    let res = parse_u32(next);
1899                    let Some(val) = res else { break };
1900                    val
1901                }),
1902                8u16 => OpGetDeviceDumpRequest::Peers({
1903                    let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
1904                    let Some(val) = res else { break };
1905                    val
1906                }),
1907                n => {
1908                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
1909                        break;
1910                    } else {
1911                        continue;
1912                    }
1913                }
1914            };
1915            return Some(Ok(res));
1916        }
1917        Some(Err(ErrorContext::new(
1918            "OpGetDeviceDumpRequest",
1919            r#type.and_then(|t| OpGetDeviceDumpRequest::attr_from_type(t)),
1920            self.orig_loc,
1921            self.buf.as_ptr().wrapping_add(pos) as usize,
1922        )))
1923    }
1924}
1925impl<'a> std::fmt::Debug for IterableOpGetDeviceDumpRequest<'_> {
1926    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1927        let mut fmt = f.debug_struct("OpGetDeviceDumpRequest");
1928        for attr in self.clone() {
1929            let attr = match attr {
1930                Ok(a) => a,
1931                Err(err) => {
1932                    fmt.finish()?;
1933                    f.write_str("Err(")?;
1934                    err.fmt(f)?;
1935                    return f.write_str(")");
1936                }
1937            };
1938            match attr {
1939                OpGetDeviceDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
1940                OpGetDeviceDumpRequest::Ifname(val) => fmt.field("Ifname", &val),
1941                OpGetDeviceDumpRequest::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
1942                OpGetDeviceDumpRequest::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
1943                OpGetDeviceDumpRequest::Flags(val) => {
1944                    fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
1945                }
1946                OpGetDeviceDumpRequest::ListenPort(val) => fmt.field("ListenPort", &val),
1947                OpGetDeviceDumpRequest::Fwmark(val) => fmt.field("Fwmark", &val),
1948                OpGetDeviceDumpRequest::Peers(val) => fmt.field("Peers", &val),
1949            };
1950        }
1951        fmt.finish()
1952    }
1953}
1954impl IterableOpGetDeviceDumpRequest<'_> {
1955    pub fn lookup_attr(
1956        &self,
1957        offset: usize,
1958        missing_type: Option<u16>,
1959    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1960        let mut stack = Vec::new();
1961        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1962        if cur == offset + PushBuiltinNfgenmsg::len() {
1963            stack.push(("OpGetDeviceDumpRequest", offset));
1964            return (
1965                stack,
1966                missing_type.and_then(|t| OpGetDeviceDumpRequest::attr_from_type(t)),
1967            );
1968        }
1969        if cur > offset || cur + self.buf.len() < offset {
1970            return (stack, None);
1971        }
1972        let mut attrs = self.clone();
1973        let mut last_off = cur + attrs.pos;
1974        let mut missing = None;
1975        while let Some(attr) = attrs.next() {
1976            let Ok(attr) = attr else { break };
1977            match attr {
1978                OpGetDeviceDumpRequest::Ifindex(val) => {
1979                    if last_off == offset {
1980                        stack.push(("Ifindex", last_off));
1981                        break;
1982                    }
1983                }
1984                OpGetDeviceDumpRequest::Ifname(val) => {
1985                    if last_off == offset {
1986                        stack.push(("Ifname", last_off));
1987                        break;
1988                    }
1989                }
1990                OpGetDeviceDumpRequest::PrivateKey(val) => {
1991                    if last_off == offset {
1992                        stack.push(("PrivateKey", last_off));
1993                        break;
1994                    }
1995                }
1996                OpGetDeviceDumpRequest::PublicKey(val) => {
1997                    if last_off == offset {
1998                        stack.push(("PublicKey", last_off));
1999                        break;
2000                    }
2001                }
2002                OpGetDeviceDumpRequest::Flags(val) => {
2003                    if last_off == offset {
2004                        stack.push(("Flags", last_off));
2005                        break;
2006                    }
2007                }
2008                OpGetDeviceDumpRequest::ListenPort(val) => {
2009                    if last_off == offset {
2010                        stack.push(("ListenPort", last_off));
2011                        break;
2012                    }
2013                }
2014                OpGetDeviceDumpRequest::Fwmark(val) => {
2015                    if last_off == offset {
2016                        stack.push(("Fwmark", last_off));
2017                        break;
2018                    }
2019                }
2020                OpGetDeviceDumpRequest::Peers(val) => {
2021                    for entry in val {
2022                        let Ok(attr) = entry else { break };
2023                        (stack, missing) = attr.lookup_attr(offset, missing_type);
2024                        if !stack.is_empty() {
2025                            break;
2026                        }
2027                    }
2028                    if !stack.is_empty() {
2029                        stack.push(("Peers", last_off));
2030                        break;
2031                    }
2032                }
2033                _ => {}
2034            };
2035            last_off = cur + attrs.pos;
2036        }
2037        if !stack.is_empty() {
2038            stack.push(("OpGetDeviceDumpRequest", cur));
2039        }
2040        (stack, missing)
2041    }
2042}
2043#[doc = "Retrieve WireGuard device.\n\nThe command should be called with one but not both of:\n* WGDEVICE_A_IFINDEX\n* WGDEVICE_A_IFNAME\n\nThe kernel will then return several messages (NLM_F_MULTI).\nIt is possible that all of the allowed IPs of a single peer will not\nfit within a single netlink message. In that case, the same peer will\nbe written in the following message, except it will only contain\nWGPEER_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\nin following messages, except those will only contain\nWGDEVICE_A_IFNAME and WGDEVICE_A_PEERS. It is then up to the receiver\nto coalesce these messages to form the complete list of peers.\n\nSince this is an NLA_F_DUMP command, the final message will always be\nNLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message\ncontains an integer error code. It is either zero or a negative error\ncode corresponding to the errno.\n"]
2044pub struct PushOpGetDeviceDumpReply<Prev: Rec> {
2045    pub(crate) prev: Option<Prev>,
2046    pub(crate) header_offset: Option<usize>,
2047}
2048impl<Prev: Rec> Rec for PushOpGetDeviceDumpReply<Prev> {
2049    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2050        self.prev.as_mut().unwrap().as_rec_mut()
2051    }
2052}
2053impl<Prev: Rec> PushOpGetDeviceDumpReply<Prev> {
2054    pub fn new(mut prev: Prev) -> Self {
2055        Self::write_header(&mut prev);
2056        Self::new_without_header(prev)
2057    }
2058    fn new_without_header(prev: Prev) -> Self {
2059        Self {
2060            prev: Some(prev),
2061            header_offset: None,
2062        }
2063    }
2064    fn write_header(prev: &mut Prev) {
2065        let mut header = PushBuiltinNfgenmsg::new();
2066        header.set_cmd(0u8);
2067        header.set_version(1u8);
2068        prev.as_rec_mut().extend(header.as_slice());
2069    }
2070    pub fn end_nested(mut self) -> Prev {
2071        let mut prev = self.prev.take().unwrap();
2072        if let Some(header_offset) = &self.header_offset {
2073            finalize_nested_header(prev.as_rec_mut(), *header_offset);
2074        }
2075        prev
2076    }
2077    pub fn push_ifindex(mut self, value: u32) -> Self {
2078        push_header(self.as_rec_mut(), 1u16, 4 as u16);
2079        self.as_rec_mut().extend(value.to_ne_bytes());
2080        self
2081    }
2082    pub fn push_ifname(mut self, value: &CStr) -> Self {
2083        push_header(
2084            self.as_rec_mut(),
2085            2u16,
2086            value.to_bytes_with_nul().len() as u16,
2087        );
2088        self.as_rec_mut().extend(value.to_bytes_with_nul());
2089        self
2090    }
2091    pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
2092        push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
2093        self.as_rec_mut().extend(value);
2094        self.as_rec_mut().push(0);
2095        self
2096    }
2097    #[doc = "Set to all zeros to remove."]
2098    pub fn push_private_key(mut self, value: &[u8]) -> Self {
2099        push_header(self.as_rec_mut(), 3u16, value.len() as u16);
2100        self.as_rec_mut().extend(value);
2101        self
2102    }
2103    pub fn push_public_key(mut self, value: &[u8]) -> Self {
2104        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
2105        self.as_rec_mut().extend(value);
2106        self
2107    }
2108    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2109    pub fn push_flags(mut self, value: u32) -> Self {
2110        push_header(self.as_rec_mut(), 5u16, 4 as u16);
2111        self.as_rec_mut().extend(value.to_ne_bytes());
2112        self
2113    }
2114    #[doc = "Set as 0 to choose randomly."]
2115    pub fn push_listen_port(mut self, value: u16) -> Self {
2116        push_header(self.as_rec_mut(), 6u16, 2 as u16);
2117        self.as_rec_mut().extend(value.to_ne_bytes());
2118        self
2119    }
2120    #[doc = "Set as 0 to disable."]
2121    pub fn push_fwmark(mut self, value: u32) -> Self {
2122        push_header(self.as_rec_mut(), 7u16, 4 as u16);
2123        self.as_rec_mut().extend(value.to_ne_bytes());
2124        self
2125    }
2126    pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
2127        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
2128        PushArrayWgpeer {
2129            prev: Some(self),
2130            header_offset: Some(header_offset),
2131            counter: 0,
2132        }
2133    }
2134}
2135impl<Prev: Rec> Drop for PushOpGetDeviceDumpReply<Prev> {
2136    fn drop(&mut self) {
2137        if let Some(prev) = &mut self.prev {
2138            if let Some(header_offset) = &self.header_offset {
2139                finalize_nested_header(prev.as_rec_mut(), *header_offset);
2140            }
2141        }
2142    }
2143}
2144#[doc = "Retrieve WireGuard device.\n\nThe command should be called with one but not both of:\n* WGDEVICE_A_IFINDEX\n* WGDEVICE_A_IFNAME\n\nThe kernel will then return several messages (NLM_F_MULTI).\nIt is possible that all of the allowed IPs of a single peer will not\nfit within a single netlink message. In that case, the same peer will\nbe written in the following message, except it will only contain\nWGPEER_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\nin following messages, except those will only contain\nWGDEVICE_A_IFNAME and WGDEVICE_A_PEERS. It is then up to the receiver\nto coalesce these messages to form the complete list of peers.\n\nSince this is an NLA_F_DUMP command, the final message will always be\nNLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message\ncontains an integer error code. It is either zero or a negative error\ncode corresponding to the errno.\n"]
2145#[derive(Clone)]
2146pub enum OpGetDeviceDumpReply<'a> {
2147    Ifindex(u32),
2148    Ifname(&'a CStr),
2149    #[doc = "Set to all zeros to remove."]
2150    PrivateKey(&'a [u8]),
2151    PublicKey(&'a [u8]),
2152    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2153    Flags(u32),
2154    #[doc = "Set as 0 to choose randomly."]
2155    ListenPort(u16),
2156    #[doc = "Set as 0 to disable."]
2157    Fwmark(u32),
2158    Peers(IterableArrayWgpeer<'a>),
2159}
2160impl<'a> IterableOpGetDeviceDumpReply<'a> {
2161    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2162        let mut iter = self.clone();
2163        iter.pos = 0;
2164        for attr in iter {
2165            if let OpGetDeviceDumpReply::Ifindex(val) = attr? {
2166                return Ok(val);
2167            }
2168        }
2169        Err(ErrorContext::new_missing(
2170            "OpGetDeviceDumpReply",
2171            "Ifindex",
2172            self.orig_loc,
2173            self.buf.as_ptr() as usize,
2174        ))
2175    }
2176    pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
2177        let mut iter = self.clone();
2178        iter.pos = 0;
2179        for attr in iter {
2180            if let OpGetDeviceDumpReply::Ifname(val) = attr? {
2181                return Ok(val);
2182            }
2183        }
2184        Err(ErrorContext::new_missing(
2185            "OpGetDeviceDumpReply",
2186            "Ifname",
2187            self.orig_loc,
2188            self.buf.as_ptr() as usize,
2189        ))
2190    }
2191    #[doc = "Set to all zeros to remove."]
2192    pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
2193        let mut iter = self.clone();
2194        iter.pos = 0;
2195        for attr in iter {
2196            if let OpGetDeviceDumpReply::PrivateKey(val) = attr? {
2197                return Ok(val);
2198            }
2199        }
2200        Err(ErrorContext::new_missing(
2201            "OpGetDeviceDumpReply",
2202            "PrivateKey",
2203            self.orig_loc,
2204            self.buf.as_ptr() as usize,
2205        ))
2206    }
2207    pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
2208        let mut iter = self.clone();
2209        iter.pos = 0;
2210        for attr in iter {
2211            if let OpGetDeviceDumpReply::PublicKey(val) = attr? {
2212                return Ok(val);
2213            }
2214        }
2215        Err(ErrorContext::new_missing(
2216            "OpGetDeviceDumpReply",
2217            "PublicKey",
2218            self.orig_loc,
2219            self.buf.as_ptr() as usize,
2220        ))
2221    }
2222    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2223    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
2224        let mut iter = self.clone();
2225        iter.pos = 0;
2226        for attr in iter {
2227            if let OpGetDeviceDumpReply::Flags(val) = attr? {
2228                return Ok(val);
2229            }
2230        }
2231        Err(ErrorContext::new_missing(
2232            "OpGetDeviceDumpReply",
2233            "Flags",
2234            self.orig_loc,
2235            self.buf.as_ptr() as usize,
2236        ))
2237    }
2238    #[doc = "Set as 0 to choose randomly."]
2239    pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
2240        let mut iter = self.clone();
2241        iter.pos = 0;
2242        for attr in iter {
2243            if let OpGetDeviceDumpReply::ListenPort(val) = attr? {
2244                return Ok(val);
2245            }
2246        }
2247        Err(ErrorContext::new_missing(
2248            "OpGetDeviceDumpReply",
2249            "ListenPort",
2250            self.orig_loc,
2251            self.buf.as_ptr() as usize,
2252        ))
2253    }
2254    #[doc = "Set as 0 to disable."]
2255    pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
2256        let mut iter = self.clone();
2257        iter.pos = 0;
2258        for attr in iter {
2259            if let OpGetDeviceDumpReply::Fwmark(val) = attr? {
2260                return Ok(val);
2261            }
2262        }
2263        Err(ErrorContext::new_missing(
2264            "OpGetDeviceDumpReply",
2265            "Fwmark",
2266            self.orig_loc,
2267            self.buf.as_ptr() as usize,
2268        ))
2269    }
2270    pub fn get_peers(
2271        &self,
2272    ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
2273        for attr in self.clone() {
2274            if let OpGetDeviceDumpReply::Peers(val) = attr? {
2275                return Ok(ArrayIterable::new(val));
2276            }
2277        }
2278        Err(ErrorContext::new_missing(
2279            "OpGetDeviceDumpReply",
2280            "Peers",
2281            self.orig_loc,
2282            self.buf.as_ptr() as usize,
2283        ))
2284    }
2285}
2286impl<'a> OpGetDeviceDumpReply<'a> {
2287    pub fn new(buf: &'a [u8]) -> IterableOpGetDeviceDumpReply<'a> {
2288        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
2289        IterableOpGetDeviceDumpReply::with_loc(attrs, buf.as_ptr() as usize)
2290    }
2291    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2292        Wgdevice::attr_from_type(r#type)
2293    }
2294}
2295#[derive(Clone, Copy, Default)]
2296pub struct IterableOpGetDeviceDumpReply<'a> {
2297    buf: &'a [u8],
2298    pos: usize,
2299    orig_loc: usize,
2300}
2301impl<'a> IterableOpGetDeviceDumpReply<'a> {
2302    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2303        Self {
2304            buf,
2305            pos: 0,
2306            orig_loc,
2307        }
2308    }
2309    pub fn get_buf(&self) -> &'a [u8] {
2310        self.buf
2311    }
2312}
2313impl<'a> Iterator for IterableOpGetDeviceDumpReply<'a> {
2314    type Item = Result<OpGetDeviceDumpReply<'a>, ErrorContext>;
2315    fn next(&mut self) -> Option<Self::Item> {
2316        if self.buf.len() == self.pos {
2317            return None;
2318        }
2319        let pos = self.pos;
2320        let mut r#type = None;
2321        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
2322            r#type = Some(header.r#type);
2323            let res = match header.r#type {
2324                1u16 => OpGetDeviceDumpReply::Ifindex({
2325                    let res = parse_u32(next);
2326                    let Some(val) = res else { break };
2327                    val
2328                }),
2329                2u16 => OpGetDeviceDumpReply::Ifname({
2330                    let res = CStr::from_bytes_with_nul(next).ok();
2331                    let Some(val) = res else { break };
2332                    val
2333                }),
2334                3u16 => OpGetDeviceDumpReply::PrivateKey({
2335                    let res = Some(next);
2336                    let Some(val) = res else { break };
2337                    val
2338                }),
2339                4u16 => OpGetDeviceDumpReply::PublicKey({
2340                    let res = Some(next);
2341                    let Some(val) = res else { break };
2342                    val
2343                }),
2344                5u16 => OpGetDeviceDumpReply::Flags({
2345                    let res = parse_u32(next);
2346                    let Some(val) = res else { break };
2347                    val
2348                }),
2349                6u16 => OpGetDeviceDumpReply::ListenPort({
2350                    let res = parse_u16(next);
2351                    let Some(val) = res else { break };
2352                    val
2353                }),
2354                7u16 => OpGetDeviceDumpReply::Fwmark({
2355                    let res = parse_u32(next);
2356                    let Some(val) = res else { break };
2357                    val
2358                }),
2359                8u16 => OpGetDeviceDumpReply::Peers({
2360                    let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
2361                    let Some(val) = res else { break };
2362                    val
2363                }),
2364                n => {
2365                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
2366                        break;
2367                    } else {
2368                        continue;
2369                    }
2370                }
2371            };
2372            return Some(Ok(res));
2373        }
2374        Some(Err(ErrorContext::new(
2375            "OpGetDeviceDumpReply",
2376            r#type.and_then(|t| OpGetDeviceDumpReply::attr_from_type(t)),
2377            self.orig_loc,
2378            self.buf.as_ptr().wrapping_add(pos) as usize,
2379        )))
2380    }
2381}
2382impl<'a> std::fmt::Debug for IterableOpGetDeviceDumpReply<'_> {
2383    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2384        let mut fmt = f.debug_struct("OpGetDeviceDumpReply");
2385        for attr in self.clone() {
2386            let attr = match attr {
2387                Ok(a) => a,
2388                Err(err) => {
2389                    fmt.finish()?;
2390                    f.write_str("Err(")?;
2391                    err.fmt(f)?;
2392                    return f.write_str(")");
2393                }
2394            };
2395            match attr {
2396                OpGetDeviceDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
2397                OpGetDeviceDumpReply::Ifname(val) => fmt.field("Ifname", &val),
2398                OpGetDeviceDumpReply::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
2399                OpGetDeviceDumpReply::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
2400                OpGetDeviceDumpReply::Flags(val) => {
2401                    fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
2402                }
2403                OpGetDeviceDumpReply::ListenPort(val) => fmt.field("ListenPort", &val),
2404                OpGetDeviceDumpReply::Fwmark(val) => fmt.field("Fwmark", &val),
2405                OpGetDeviceDumpReply::Peers(val) => fmt.field("Peers", &val),
2406            };
2407        }
2408        fmt.finish()
2409    }
2410}
2411impl IterableOpGetDeviceDumpReply<'_> {
2412    pub fn lookup_attr(
2413        &self,
2414        offset: usize,
2415        missing_type: Option<u16>,
2416    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2417        let mut stack = Vec::new();
2418        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2419        if cur == offset + PushBuiltinNfgenmsg::len() {
2420            stack.push(("OpGetDeviceDumpReply", offset));
2421            return (
2422                stack,
2423                missing_type.and_then(|t| OpGetDeviceDumpReply::attr_from_type(t)),
2424            );
2425        }
2426        if cur > offset || cur + self.buf.len() < offset {
2427            return (stack, None);
2428        }
2429        let mut attrs = self.clone();
2430        let mut last_off = cur + attrs.pos;
2431        let mut missing = None;
2432        while let Some(attr) = attrs.next() {
2433            let Ok(attr) = attr else { break };
2434            match attr {
2435                OpGetDeviceDumpReply::Ifindex(val) => {
2436                    if last_off == offset {
2437                        stack.push(("Ifindex", last_off));
2438                        break;
2439                    }
2440                }
2441                OpGetDeviceDumpReply::Ifname(val) => {
2442                    if last_off == offset {
2443                        stack.push(("Ifname", last_off));
2444                        break;
2445                    }
2446                }
2447                OpGetDeviceDumpReply::PrivateKey(val) => {
2448                    if last_off == offset {
2449                        stack.push(("PrivateKey", last_off));
2450                        break;
2451                    }
2452                }
2453                OpGetDeviceDumpReply::PublicKey(val) => {
2454                    if last_off == offset {
2455                        stack.push(("PublicKey", last_off));
2456                        break;
2457                    }
2458                }
2459                OpGetDeviceDumpReply::Flags(val) => {
2460                    if last_off == offset {
2461                        stack.push(("Flags", last_off));
2462                        break;
2463                    }
2464                }
2465                OpGetDeviceDumpReply::ListenPort(val) => {
2466                    if last_off == offset {
2467                        stack.push(("ListenPort", last_off));
2468                        break;
2469                    }
2470                }
2471                OpGetDeviceDumpReply::Fwmark(val) => {
2472                    if last_off == offset {
2473                        stack.push(("Fwmark", last_off));
2474                        break;
2475                    }
2476                }
2477                OpGetDeviceDumpReply::Peers(val) => {
2478                    for entry in val {
2479                        let Ok(attr) = entry else { break };
2480                        (stack, missing) = attr.lookup_attr(offset, missing_type);
2481                        if !stack.is_empty() {
2482                            break;
2483                        }
2484                    }
2485                    if !stack.is_empty() {
2486                        stack.push(("Peers", last_off));
2487                        break;
2488                    }
2489                }
2490                _ => {}
2491            };
2492            last_off = cur + attrs.pos;
2493        }
2494        if !stack.is_empty() {
2495            stack.push(("OpGetDeviceDumpReply", cur));
2496        }
2497        (stack, missing)
2498    }
2499}
2500#[derive(Debug)]
2501pub struct RequestOpGetDeviceDumpRequest<'r> {
2502    request: Request<'r>,
2503}
2504impl<'r> RequestOpGetDeviceDumpRequest<'r> {
2505    pub fn new(mut request: Request<'r>) -> Self {
2506        PushOpGetDeviceDumpRequest::write_header(&mut request.buf_mut());
2507        Self {
2508            request: request.set_dump(),
2509        }
2510    }
2511    pub fn encode(&mut self) -> PushOpGetDeviceDumpRequest<&mut Vec<u8>> {
2512        PushOpGetDeviceDumpRequest::new_without_header(self.request.buf_mut())
2513    }
2514    pub fn into_encoder(self) -> PushOpGetDeviceDumpRequest<RequestBuf<'r>> {
2515        PushOpGetDeviceDumpRequest::new_without_header(self.request.buf)
2516    }
2517}
2518impl NetlinkRequest for RequestOpGetDeviceDumpRequest<'_> {
2519    type ReplyType<'buf> = IterableOpGetDeviceDumpReply<'buf>;
2520    fn protocol(&self) -> Protocol {
2521        Protocol::Generic("wireguard".as_bytes())
2522    }
2523    fn flags(&self) -> u16 {
2524        self.request.flags
2525    }
2526    fn payload(&self) -> &[u8] {
2527        self.request.buf()
2528    }
2529    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2530        OpGetDeviceDumpReply::new(buf)
2531    }
2532    fn lookup(
2533        buf: &[u8],
2534        offset: usize,
2535        missing_type: Option<u16>,
2536    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2537        OpGetDeviceDumpRequest::new(buf).lookup_attr(offset, missing_type)
2538    }
2539}
2540#[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\nthe maximum message length accepted by the kernel. In that case,\nseveral messages should be sent one after another, with each\nsuccessive one filling in information not contained in the prior.\nNote that if WGDEVICE_F_REPLACE_PEERS is specified in the first\nmessage, it probably should not be specified in fragments that come\nafter, so that the list of peers is only cleared the first time but\nappended 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"]
2541pub struct PushOpSetDeviceDoRequest<Prev: Rec> {
2542    pub(crate) prev: Option<Prev>,
2543    pub(crate) header_offset: Option<usize>,
2544}
2545impl<Prev: Rec> Rec for PushOpSetDeviceDoRequest<Prev> {
2546    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2547        self.prev.as_mut().unwrap().as_rec_mut()
2548    }
2549}
2550impl<Prev: Rec> PushOpSetDeviceDoRequest<Prev> {
2551    pub fn new(mut prev: Prev) -> Self {
2552        Self::write_header(&mut prev);
2553        Self::new_without_header(prev)
2554    }
2555    fn new_without_header(prev: Prev) -> Self {
2556        Self {
2557            prev: Some(prev),
2558            header_offset: None,
2559        }
2560    }
2561    fn write_header(prev: &mut Prev) {
2562        let mut header = PushBuiltinNfgenmsg::new();
2563        header.set_cmd(1u8);
2564        header.set_version(1u8);
2565        prev.as_rec_mut().extend(header.as_slice());
2566    }
2567    pub fn end_nested(mut self) -> Prev {
2568        let mut prev = self.prev.take().unwrap();
2569        if let Some(header_offset) = &self.header_offset {
2570            finalize_nested_header(prev.as_rec_mut(), *header_offset);
2571        }
2572        prev
2573    }
2574    pub fn push_ifindex(mut self, value: u32) -> Self {
2575        push_header(self.as_rec_mut(), 1u16, 4 as u16);
2576        self.as_rec_mut().extend(value.to_ne_bytes());
2577        self
2578    }
2579    pub fn push_ifname(mut self, value: &CStr) -> Self {
2580        push_header(
2581            self.as_rec_mut(),
2582            2u16,
2583            value.to_bytes_with_nul().len() as u16,
2584        );
2585        self.as_rec_mut().extend(value.to_bytes_with_nul());
2586        self
2587    }
2588    pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
2589        push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
2590        self.as_rec_mut().extend(value);
2591        self.as_rec_mut().push(0);
2592        self
2593    }
2594    #[doc = "Set to all zeros to remove."]
2595    pub fn push_private_key(mut self, value: &[u8]) -> Self {
2596        push_header(self.as_rec_mut(), 3u16, value.len() as u16);
2597        self.as_rec_mut().extend(value);
2598        self
2599    }
2600    pub fn push_public_key(mut self, value: &[u8]) -> Self {
2601        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
2602        self.as_rec_mut().extend(value);
2603        self
2604    }
2605    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2606    pub fn push_flags(mut self, value: u32) -> Self {
2607        push_header(self.as_rec_mut(), 5u16, 4 as u16);
2608        self.as_rec_mut().extend(value.to_ne_bytes());
2609        self
2610    }
2611    #[doc = "Set as 0 to choose randomly."]
2612    pub fn push_listen_port(mut self, value: u16) -> Self {
2613        push_header(self.as_rec_mut(), 6u16, 2 as u16);
2614        self.as_rec_mut().extend(value.to_ne_bytes());
2615        self
2616    }
2617    #[doc = "Set as 0 to disable."]
2618    pub fn push_fwmark(mut self, value: u32) -> Self {
2619        push_header(self.as_rec_mut(), 7u16, 4 as u16);
2620        self.as_rec_mut().extend(value.to_ne_bytes());
2621        self
2622    }
2623    pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
2624        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
2625        PushArrayWgpeer {
2626            prev: Some(self),
2627            header_offset: Some(header_offset),
2628            counter: 0,
2629        }
2630    }
2631}
2632impl<Prev: Rec> Drop for PushOpSetDeviceDoRequest<Prev> {
2633    fn drop(&mut self) {
2634        if let Some(prev) = &mut self.prev {
2635            if let Some(header_offset) = &self.header_offset {
2636                finalize_nested_header(prev.as_rec_mut(), *header_offset);
2637            }
2638        }
2639    }
2640}
2641#[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\nthe maximum message length accepted by the kernel. In that case,\nseveral messages should be sent one after another, with each\nsuccessive one filling in information not contained in the prior.\nNote that if WGDEVICE_F_REPLACE_PEERS is specified in the first\nmessage, it probably should not be specified in fragments that come\nafter, so that the list of peers is only cleared the first time but\nappended 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"]
2642#[derive(Clone)]
2643pub enum OpSetDeviceDoRequest<'a> {
2644    Ifindex(u32),
2645    Ifname(&'a CStr),
2646    #[doc = "Set to all zeros to remove."]
2647    PrivateKey(&'a [u8]),
2648    PublicKey(&'a [u8]),
2649    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2650    Flags(u32),
2651    #[doc = "Set as 0 to choose randomly."]
2652    ListenPort(u16),
2653    #[doc = "Set as 0 to disable."]
2654    Fwmark(u32),
2655    Peers(IterableArrayWgpeer<'a>),
2656}
2657impl<'a> IterableOpSetDeviceDoRequest<'a> {
2658    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2659        let mut iter = self.clone();
2660        iter.pos = 0;
2661        for attr in iter {
2662            if let OpSetDeviceDoRequest::Ifindex(val) = attr? {
2663                return Ok(val);
2664            }
2665        }
2666        Err(ErrorContext::new_missing(
2667            "OpSetDeviceDoRequest",
2668            "Ifindex",
2669            self.orig_loc,
2670            self.buf.as_ptr() as usize,
2671        ))
2672    }
2673    pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
2674        let mut iter = self.clone();
2675        iter.pos = 0;
2676        for attr in iter {
2677            if let OpSetDeviceDoRequest::Ifname(val) = attr? {
2678                return Ok(val);
2679            }
2680        }
2681        Err(ErrorContext::new_missing(
2682            "OpSetDeviceDoRequest",
2683            "Ifname",
2684            self.orig_loc,
2685            self.buf.as_ptr() as usize,
2686        ))
2687    }
2688    #[doc = "Set to all zeros to remove."]
2689    pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
2690        let mut iter = self.clone();
2691        iter.pos = 0;
2692        for attr in iter {
2693            if let OpSetDeviceDoRequest::PrivateKey(val) = attr? {
2694                return Ok(val);
2695            }
2696        }
2697        Err(ErrorContext::new_missing(
2698            "OpSetDeviceDoRequest",
2699            "PrivateKey",
2700            self.orig_loc,
2701            self.buf.as_ptr() as usize,
2702        ))
2703    }
2704    pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
2705        let mut iter = self.clone();
2706        iter.pos = 0;
2707        for attr in iter {
2708            if let OpSetDeviceDoRequest::PublicKey(val) = attr? {
2709                return Ok(val);
2710            }
2711        }
2712        Err(ErrorContext::new_missing(
2713            "OpSetDeviceDoRequest",
2714            "PublicKey",
2715            self.orig_loc,
2716            self.buf.as_ptr() as usize,
2717        ))
2718    }
2719    #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2720    pub fn get_flags(&self) -> Result<u32, ErrorContext> {
2721        let mut iter = self.clone();
2722        iter.pos = 0;
2723        for attr in iter {
2724            if let OpSetDeviceDoRequest::Flags(val) = attr? {
2725                return Ok(val);
2726            }
2727        }
2728        Err(ErrorContext::new_missing(
2729            "OpSetDeviceDoRequest",
2730            "Flags",
2731            self.orig_loc,
2732            self.buf.as_ptr() as usize,
2733        ))
2734    }
2735    #[doc = "Set as 0 to choose randomly."]
2736    pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
2737        let mut iter = self.clone();
2738        iter.pos = 0;
2739        for attr in iter {
2740            if let OpSetDeviceDoRequest::ListenPort(val) = attr? {
2741                return Ok(val);
2742            }
2743        }
2744        Err(ErrorContext::new_missing(
2745            "OpSetDeviceDoRequest",
2746            "ListenPort",
2747            self.orig_loc,
2748            self.buf.as_ptr() as usize,
2749        ))
2750    }
2751    #[doc = "Set as 0 to disable."]
2752    pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
2753        let mut iter = self.clone();
2754        iter.pos = 0;
2755        for attr in iter {
2756            if let OpSetDeviceDoRequest::Fwmark(val) = attr? {
2757                return Ok(val);
2758            }
2759        }
2760        Err(ErrorContext::new_missing(
2761            "OpSetDeviceDoRequest",
2762            "Fwmark",
2763            self.orig_loc,
2764            self.buf.as_ptr() as usize,
2765        ))
2766    }
2767    pub fn get_peers(
2768        &self,
2769    ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
2770        for attr in self.clone() {
2771            if let OpSetDeviceDoRequest::Peers(val) = attr? {
2772                return Ok(ArrayIterable::new(val));
2773            }
2774        }
2775        Err(ErrorContext::new_missing(
2776            "OpSetDeviceDoRequest",
2777            "Peers",
2778            self.orig_loc,
2779            self.buf.as_ptr() as usize,
2780        ))
2781    }
2782}
2783impl<'a> OpSetDeviceDoRequest<'a> {
2784    pub fn new(buf: &'a [u8]) -> IterableOpSetDeviceDoRequest<'a> {
2785        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
2786        IterableOpSetDeviceDoRequest::with_loc(attrs, buf.as_ptr() as usize)
2787    }
2788    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2789        Wgdevice::attr_from_type(r#type)
2790    }
2791}
2792#[derive(Clone, Copy, Default)]
2793pub struct IterableOpSetDeviceDoRequest<'a> {
2794    buf: &'a [u8],
2795    pos: usize,
2796    orig_loc: usize,
2797}
2798impl<'a> IterableOpSetDeviceDoRequest<'a> {
2799    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2800        Self {
2801            buf,
2802            pos: 0,
2803            orig_loc,
2804        }
2805    }
2806    pub fn get_buf(&self) -> &'a [u8] {
2807        self.buf
2808    }
2809}
2810impl<'a> Iterator for IterableOpSetDeviceDoRequest<'a> {
2811    type Item = Result<OpSetDeviceDoRequest<'a>, ErrorContext>;
2812    fn next(&mut self) -> Option<Self::Item> {
2813        if self.buf.len() == self.pos {
2814            return None;
2815        }
2816        let pos = self.pos;
2817        let mut r#type = None;
2818        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
2819            r#type = Some(header.r#type);
2820            let res = match header.r#type {
2821                1u16 => OpSetDeviceDoRequest::Ifindex({
2822                    let res = parse_u32(next);
2823                    let Some(val) = res else { break };
2824                    val
2825                }),
2826                2u16 => OpSetDeviceDoRequest::Ifname({
2827                    let res = CStr::from_bytes_with_nul(next).ok();
2828                    let Some(val) = res else { break };
2829                    val
2830                }),
2831                3u16 => OpSetDeviceDoRequest::PrivateKey({
2832                    let res = Some(next);
2833                    let Some(val) = res else { break };
2834                    val
2835                }),
2836                4u16 => OpSetDeviceDoRequest::PublicKey({
2837                    let res = Some(next);
2838                    let Some(val) = res else { break };
2839                    val
2840                }),
2841                5u16 => OpSetDeviceDoRequest::Flags({
2842                    let res = parse_u32(next);
2843                    let Some(val) = res else { break };
2844                    val
2845                }),
2846                6u16 => OpSetDeviceDoRequest::ListenPort({
2847                    let res = parse_u16(next);
2848                    let Some(val) = res else { break };
2849                    val
2850                }),
2851                7u16 => OpSetDeviceDoRequest::Fwmark({
2852                    let res = parse_u32(next);
2853                    let Some(val) = res else { break };
2854                    val
2855                }),
2856                8u16 => OpSetDeviceDoRequest::Peers({
2857                    let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
2858                    let Some(val) = res else { break };
2859                    val
2860                }),
2861                n => {
2862                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
2863                        break;
2864                    } else {
2865                        continue;
2866                    }
2867                }
2868            };
2869            return Some(Ok(res));
2870        }
2871        Some(Err(ErrorContext::new(
2872            "OpSetDeviceDoRequest",
2873            r#type.and_then(|t| OpSetDeviceDoRequest::attr_from_type(t)),
2874            self.orig_loc,
2875            self.buf.as_ptr().wrapping_add(pos) as usize,
2876        )))
2877    }
2878}
2879impl<'a> std::fmt::Debug for IterableOpSetDeviceDoRequest<'_> {
2880    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2881        let mut fmt = f.debug_struct("OpSetDeviceDoRequest");
2882        for attr in self.clone() {
2883            let attr = match attr {
2884                Ok(a) => a,
2885                Err(err) => {
2886                    fmt.finish()?;
2887                    f.write_str("Err(")?;
2888                    err.fmt(f)?;
2889                    return f.write_str(")");
2890                }
2891            };
2892            match attr {
2893                OpSetDeviceDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
2894                OpSetDeviceDoRequest::Ifname(val) => fmt.field("Ifname", &val),
2895                OpSetDeviceDoRequest::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
2896                OpSetDeviceDoRequest::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
2897                OpSetDeviceDoRequest::Flags(val) => {
2898                    fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
2899                }
2900                OpSetDeviceDoRequest::ListenPort(val) => fmt.field("ListenPort", &val),
2901                OpSetDeviceDoRequest::Fwmark(val) => fmt.field("Fwmark", &val),
2902                OpSetDeviceDoRequest::Peers(val) => fmt.field("Peers", &val),
2903            };
2904        }
2905        fmt.finish()
2906    }
2907}
2908impl IterableOpSetDeviceDoRequest<'_> {
2909    pub fn lookup_attr(
2910        &self,
2911        offset: usize,
2912        missing_type: Option<u16>,
2913    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2914        let mut stack = Vec::new();
2915        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2916        if cur == offset + PushBuiltinNfgenmsg::len() {
2917            stack.push(("OpSetDeviceDoRequest", offset));
2918            return (
2919                stack,
2920                missing_type.and_then(|t| OpSetDeviceDoRequest::attr_from_type(t)),
2921            );
2922        }
2923        if cur > offset || cur + self.buf.len() < offset {
2924            return (stack, None);
2925        }
2926        let mut attrs = self.clone();
2927        let mut last_off = cur + attrs.pos;
2928        let mut missing = None;
2929        while let Some(attr) = attrs.next() {
2930            let Ok(attr) = attr else { break };
2931            match attr {
2932                OpSetDeviceDoRequest::Ifindex(val) => {
2933                    if last_off == offset {
2934                        stack.push(("Ifindex", last_off));
2935                        break;
2936                    }
2937                }
2938                OpSetDeviceDoRequest::Ifname(val) => {
2939                    if last_off == offset {
2940                        stack.push(("Ifname", last_off));
2941                        break;
2942                    }
2943                }
2944                OpSetDeviceDoRequest::PrivateKey(val) => {
2945                    if last_off == offset {
2946                        stack.push(("PrivateKey", last_off));
2947                        break;
2948                    }
2949                }
2950                OpSetDeviceDoRequest::PublicKey(val) => {
2951                    if last_off == offset {
2952                        stack.push(("PublicKey", last_off));
2953                        break;
2954                    }
2955                }
2956                OpSetDeviceDoRequest::Flags(val) => {
2957                    if last_off == offset {
2958                        stack.push(("Flags", last_off));
2959                        break;
2960                    }
2961                }
2962                OpSetDeviceDoRequest::ListenPort(val) => {
2963                    if last_off == offset {
2964                        stack.push(("ListenPort", last_off));
2965                        break;
2966                    }
2967                }
2968                OpSetDeviceDoRequest::Fwmark(val) => {
2969                    if last_off == offset {
2970                        stack.push(("Fwmark", last_off));
2971                        break;
2972                    }
2973                }
2974                OpSetDeviceDoRequest::Peers(val) => {
2975                    for entry in val {
2976                        let Ok(attr) = entry else { break };
2977                        (stack, missing) = attr.lookup_attr(offset, missing_type);
2978                        if !stack.is_empty() {
2979                            break;
2980                        }
2981                    }
2982                    if !stack.is_empty() {
2983                        stack.push(("Peers", last_off));
2984                        break;
2985                    }
2986                }
2987                _ => {}
2988            };
2989            last_off = cur + attrs.pos;
2990        }
2991        if !stack.is_empty() {
2992            stack.push(("OpSetDeviceDoRequest", cur));
2993        }
2994        (stack, missing)
2995    }
2996}
2997#[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\nthe maximum message length accepted by the kernel. In that case,\nseveral messages should be sent one after another, with each\nsuccessive one filling in information not contained in the prior.\nNote that if WGDEVICE_F_REPLACE_PEERS is specified in the first\nmessage, it probably should not be specified in fragments that come\nafter, so that the list of peers is only cleared the first time but\nappended 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"]
2998pub struct PushOpSetDeviceDoReply<Prev: Rec> {
2999    pub(crate) prev: Option<Prev>,
3000    pub(crate) header_offset: Option<usize>,
3001}
3002impl<Prev: Rec> Rec for PushOpSetDeviceDoReply<Prev> {
3003    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3004        self.prev.as_mut().unwrap().as_rec_mut()
3005    }
3006}
3007impl<Prev: Rec> PushOpSetDeviceDoReply<Prev> {
3008    pub fn new(mut prev: Prev) -> Self {
3009        Self::write_header(&mut prev);
3010        Self::new_without_header(prev)
3011    }
3012    fn new_without_header(prev: Prev) -> Self {
3013        Self {
3014            prev: Some(prev),
3015            header_offset: None,
3016        }
3017    }
3018    fn write_header(prev: &mut Prev) {
3019        let mut header = PushBuiltinNfgenmsg::new();
3020        header.set_cmd(1u8);
3021        header.set_version(1u8);
3022        prev.as_rec_mut().extend(header.as_slice());
3023    }
3024    pub fn end_nested(mut self) -> Prev {
3025        let mut prev = self.prev.take().unwrap();
3026        if let Some(header_offset) = &self.header_offset {
3027            finalize_nested_header(prev.as_rec_mut(), *header_offset);
3028        }
3029        prev
3030    }
3031}
3032impl<Prev: Rec> Drop for PushOpSetDeviceDoReply<Prev> {
3033    fn drop(&mut self) {
3034        if let Some(prev) = &mut self.prev {
3035            if let Some(header_offset) = &self.header_offset {
3036                finalize_nested_header(prev.as_rec_mut(), *header_offset);
3037            }
3038        }
3039    }
3040}
3041#[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\nthe maximum message length accepted by the kernel. In that case,\nseveral messages should be sent one after another, with each\nsuccessive one filling in information not contained in the prior.\nNote that if WGDEVICE_F_REPLACE_PEERS is specified in the first\nmessage, it probably should not be specified in fragments that come\nafter, so that the list of peers is only cleared the first time but\nappended 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"]
3042#[derive(Clone)]
3043pub enum OpSetDeviceDoReply {}
3044impl<'a> IterableOpSetDeviceDoReply<'a> {}
3045impl OpSetDeviceDoReply {
3046    pub fn new(buf: &'_ [u8]) -> IterableOpSetDeviceDoReply<'_> {
3047        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
3048        IterableOpSetDeviceDoReply::with_loc(attrs, buf.as_ptr() as usize)
3049    }
3050    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3051        Wgdevice::attr_from_type(r#type)
3052    }
3053}
3054#[derive(Clone, Copy, Default)]
3055pub struct IterableOpSetDeviceDoReply<'a> {
3056    buf: &'a [u8],
3057    pos: usize,
3058    orig_loc: usize,
3059}
3060impl<'a> IterableOpSetDeviceDoReply<'a> {
3061    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3062        Self {
3063            buf,
3064            pos: 0,
3065            orig_loc,
3066        }
3067    }
3068    pub fn get_buf(&self) -> &'a [u8] {
3069        self.buf
3070    }
3071}
3072impl<'a> Iterator for IterableOpSetDeviceDoReply<'a> {
3073    type Item = Result<OpSetDeviceDoReply, ErrorContext>;
3074    fn next(&mut self) -> Option<Self::Item> {
3075        if self.buf.len() == self.pos {
3076            return None;
3077        }
3078        let pos = self.pos;
3079        let mut r#type = None;
3080        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
3081            r#type = Some(header.r#type);
3082            let res = match header.r#type {
3083                n => {
3084                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
3085                        break;
3086                    } else {
3087                        continue;
3088                    }
3089                }
3090            };
3091            return Some(Ok(res));
3092        }
3093        Some(Err(ErrorContext::new(
3094            "OpSetDeviceDoReply",
3095            r#type.and_then(|t| OpSetDeviceDoReply::attr_from_type(t)),
3096            self.orig_loc,
3097            self.buf.as_ptr().wrapping_add(pos) as usize,
3098        )))
3099    }
3100}
3101impl std::fmt::Debug for IterableOpSetDeviceDoReply<'_> {
3102    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3103        let mut fmt = f.debug_struct("OpSetDeviceDoReply");
3104        for attr in self.clone() {
3105            let attr = match attr {
3106                Ok(a) => a,
3107                Err(err) => {
3108                    fmt.finish()?;
3109                    f.write_str("Err(")?;
3110                    err.fmt(f)?;
3111                    return f.write_str(")");
3112                }
3113            };
3114            match attr {};
3115        }
3116        fmt.finish()
3117    }
3118}
3119impl IterableOpSetDeviceDoReply<'_> {
3120    pub fn lookup_attr(
3121        &self,
3122        offset: usize,
3123        missing_type: Option<u16>,
3124    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3125        let mut stack = Vec::new();
3126        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3127        if cur == offset + PushBuiltinNfgenmsg::len() {
3128            stack.push(("OpSetDeviceDoReply", offset));
3129            return (
3130                stack,
3131                missing_type.and_then(|t| OpSetDeviceDoReply::attr_from_type(t)),
3132            );
3133        }
3134        (stack, None)
3135    }
3136}
3137#[derive(Debug)]
3138pub struct RequestOpSetDeviceDoRequest<'r> {
3139    request: Request<'r>,
3140}
3141impl<'r> RequestOpSetDeviceDoRequest<'r> {
3142    pub fn new(mut request: Request<'r>) -> Self {
3143        PushOpSetDeviceDoRequest::write_header(&mut request.buf_mut());
3144        Self { request: request }
3145    }
3146    pub fn encode(&mut self) -> PushOpSetDeviceDoRequest<&mut Vec<u8>> {
3147        PushOpSetDeviceDoRequest::new_without_header(self.request.buf_mut())
3148    }
3149    pub fn into_encoder(self) -> PushOpSetDeviceDoRequest<RequestBuf<'r>> {
3150        PushOpSetDeviceDoRequest::new_without_header(self.request.buf)
3151    }
3152}
3153impl NetlinkRequest for RequestOpSetDeviceDoRequest<'_> {
3154    type ReplyType<'buf> = IterableOpSetDeviceDoReply<'buf>;
3155    fn protocol(&self) -> Protocol {
3156        Protocol::Generic("wireguard".as_bytes())
3157    }
3158    fn flags(&self) -> u16 {
3159        self.request.flags
3160    }
3161    fn payload(&self) -> &[u8] {
3162        self.request.buf()
3163    }
3164    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
3165        OpSetDeviceDoReply::new(buf)
3166    }
3167    fn lookup(
3168        buf: &[u8],
3169        offset: usize,
3170        missing_type: Option<u16>,
3171    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3172        OpSetDeviceDoRequest::new(buf).lookup_attr(offset, missing_type)
3173    }
3174}
3175use crate::traits::LookupFn;
3176use crate::utils::RequestBuf;
3177#[derive(Debug)]
3178pub struct Request<'buf> {
3179    buf: RequestBuf<'buf>,
3180    flags: u16,
3181    writeback: Option<&'buf mut Option<RequestInfo>>,
3182}
3183#[allow(unused)]
3184#[derive(Debug, Clone)]
3185pub struct RequestInfo {
3186    protocol: Protocol,
3187    flags: u16,
3188    name: &'static str,
3189    lookup: LookupFn,
3190}
3191impl Request<'static> {
3192    pub fn new() -> Self {
3193        Self::new_from_buf(Vec::new())
3194    }
3195    pub fn new_from_buf(buf: Vec<u8>) -> Self {
3196        Self {
3197            flags: 0,
3198            buf: RequestBuf::Own(buf),
3199            writeback: None,
3200        }
3201    }
3202    pub fn into_buf(self) -> Vec<u8> {
3203        match self.buf {
3204            RequestBuf::Own(buf) => buf,
3205            _ => unreachable!(),
3206        }
3207    }
3208}
3209impl<'buf> Request<'buf> {
3210    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
3211        buf.clear();
3212        Self::new_extend(buf)
3213    }
3214    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
3215        Self {
3216            flags: 0,
3217            buf: RequestBuf::Ref(buf),
3218            writeback: None,
3219        }
3220    }
3221    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
3222        let Some(writeback) = &mut self.writeback else {
3223            return;
3224        };
3225        **writeback = Some(RequestInfo {
3226            protocol,
3227            flags: self.flags,
3228            name,
3229            lookup,
3230        })
3231    }
3232    pub fn buf(&self) -> &Vec<u8> {
3233        self.buf.buf()
3234    }
3235    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3236        self.buf.buf_mut()
3237    }
3238    #[doc = "Set `NLM_F_CREATE` flag"]
3239    pub fn set_create(mut self) -> Self {
3240        self.flags |= consts::NLM_F_CREATE as u16;
3241        self
3242    }
3243    #[doc = "Set `NLM_F_EXCL` flag"]
3244    pub fn set_excl(mut self) -> Self {
3245        self.flags |= consts::NLM_F_EXCL as u16;
3246        self
3247    }
3248    #[doc = "Set `NLM_F_REPLACE` flag"]
3249    pub fn set_replace(mut self) -> Self {
3250        self.flags |= consts::NLM_F_REPLACE as u16;
3251        self
3252    }
3253    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
3254    pub fn set_change(self) -> Self {
3255        self.set_create().set_replace()
3256    }
3257    #[doc = "Set `NLM_F_APPEND` flag"]
3258    pub fn set_append(mut self) -> Self {
3259        self.flags |= consts::NLM_F_APPEND as u16;
3260        self
3261    }
3262    #[doc = "Set `NLM_F_DUMP` flag"]
3263    fn set_dump(mut self) -> Self {
3264        self.flags |= consts::NLM_F_DUMP as u16;
3265        self
3266    }
3267    pub fn op_get_device_dump_request(self) -> RequestOpGetDeviceDumpRequest<'buf> {
3268        let mut res = RequestOpGetDeviceDumpRequest::new(self);
3269        res.request.do_writeback(
3270            res.protocol(),
3271            "op-get-device-dump-request",
3272            RequestOpGetDeviceDumpRequest::lookup,
3273        );
3274        res
3275    }
3276    pub fn op_set_device_do_request(self) -> RequestOpSetDeviceDoRequest<'buf> {
3277        let mut res = RequestOpSetDeviceDoRequest::new(self);
3278        res.request.do_writeback(
3279            res.protocol(),
3280            "op-set-device-do-request",
3281            RequestOpSetDeviceDoRequest::lookup,
3282        );
3283        res
3284    }
3285}