Skip to main content

netlink_bindings/wireguard/
mod.rs

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