Skip to main content

netlink_bindings/psp/
mod.rs

1#![doc = "PSP Security Protocol Generic Netlink family.\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)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "psp";
17pub const PROTONAME_CSTR: &CStr = c"psp";
18#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
19#[derive(Debug, Clone, Copy)]
20pub enum Version {
21    Hdr0AesGcm128 = 0,
22    Hdr0AesGcm256 = 1,
23    Hdr0AesGmac128 = 2,
24    Hdr0AesGmac256 = 3,
25}
26impl Version {
27    pub fn from_value(value: u64) -> Option<Self> {
28        Some(match value {
29            0 => Self::Hdr0AesGcm128,
30            1 => Self::Hdr0AesGcm256,
31            2 => Self::Hdr0AesGmac128,
32            3 => Self::Hdr0AesGmac256,
33            _ => return None,
34        })
35    }
36}
37#[derive(Clone)]
38pub enum AssocDevInfo {
39    #[doc = "ifindex of an associated network device.\n"]
40    Ifindex(u32),
41    #[doc = "Network namespace ID of the associated device.\n"]
42    Nsid(i32),
43}
44impl<'a> IterableAssocDevInfo<'a> {
45    #[doc = "ifindex of an associated network device.\n"]
46    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
47        let mut iter = self.clone();
48        iter.pos = 0;
49        for attr in iter {
50            if let Ok(AssocDevInfo::Ifindex(val)) = attr {
51                return Ok(val);
52            }
53        }
54        Err(ErrorContext::new_missing(
55            "AssocDevInfo",
56            "Ifindex",
57            self.orig_loc,
58            self.buf.as_ptr() as usize,
59        ))
60    }
61    #[doc = "Network namespace ID of the associated device.\n"]
62    pub fn get_nsid(&self) -> Result<i32, ErrorContext> {
63        let mut iter = self.clone();
64        iter.pos = 0;
65        for attr in iter {
66            if let Ok(AssocDevInfo::Nsid(val)) = attr {
67                return Ok(val);
68            }
69        }
70        Err(ErrorContext::new_missing(
71            "AssocDevInfo",
72            "Nsid",
73            self.orig_loc,
74            self.buf.as_ptr() as usize,
75        ))
76    }
77}
78impl AssocDevInfo {
79    pub fn new<'a>(buf: &'a [u8]) -> IterableAssocDevInfo<'a> {
80        IterableAssocDevInfo::with_loc(buf, buf.as_ptr() as usize)
81    }
82    fn attr_from_type(r#type: u16) -> Option<&'static str> {
83        let res = match r#type {
84            1u16 => "Ifindex",
85            2u16 => "Nsid",
86            _ => return None,
87        };
88        Some(res)
89    }
90}
91#[derive(Clone, Copy, Default)]
92pub struct IterableAssocDevInfo<'a> {
93    buf: &'a [u8],
94    pos: usize,
95    orig_loc: usize,
96}
97impl<'a> IterableAssocDevInfo<'a> {
98    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
99        Self {
100            buf,
101            pos: 0,
102            orig_loc,
103        }
104    }
105    pub fn get_buf(&self) -> &'a [u8] {
106        self.buf
107    }
108}
109impl<'a> Iterator for IterableAssocDevInfo<'a> {
110    type Item = Result<AssocDevInfo, ErrorContext>;
111    fn next(&mut self) -> Option<Self::Item> {
112        let mut pos;
113        let mut r#type;
114        loop {
115            pos = self.pos;
116            r#type = None;
117            if self.buf.len() == self.pos {
118                return None;
119            }
120            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
121                self.pos = self.buf.len();
122                break;
123            };
124            r#type = Some(header.r#type);
125            let res = match header.r#type {
126                1u16 => AssocDevInfo::Ifindex({
127                    let res = parse_u32(next);
128                    let Some(val) = res else { break };
129                    val
130                }),
131                2u16 => AssocDevInfo::Nsid({
132                    let res = parse_i32(next);
133                    let Some(val) = res else { break };
134                    val
135                }),
136                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
137                n => continue,
138            };
139            return Some(Ok(res));
140        }
141        Some(Err(ErrorContext::new(
142            "AssocDevInfo",
143            r#type.and_then(|t| AssocDevInfo::attr_from_type(t)),
144            self.orig_loc,
145            self.buf.as_ptr().wrapping_add(pos) as usize,
146        )))
147    }
148}
149impl std::fmt::Debug for IterableAssocDevInfo<'_> {
150    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151        let mut fmt = f.debug_struct("AssocDevInfo");
152        for attr in self.clone() {
153            let attr = match attr {
154                Ok(a) => a,
155                Err(err) => {
156                    fmt.finish()?;
157                    f.write_str("Err(")?;
158                    err.fmt(f)?;
159                    return f.write_str(")");
160                }
161            };
162            match attr {
163                AssocDevInfo::Ifindex(val) => fmt.field("Ifindex", &val),
164                AssocDevInfo::Nsid(val) => fmt.field("Nsid", &val),
165            };
166        }
167        fmt.finish()
168    }
169}
170impl IterableAssocDevInfo<'_> {
171    pub fn lookup_attr(
172        &self,
173        offset: usize,
174        missing_type: Option<u16>,
175    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
176        let mut stack = Vec::new();
177        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
178        if missing_type.is_some() && cur == offset {
179            stack.push(("AssocDevInfo", offset));
180            return (
181                stack,
182                missing_type.and_then(|t| AssocDevInfo::attr_from_type(t)),
183            );
184        }
185        if cur > offset || cur + self.buf.len() < offset {
186            return (stack, None);
187        }
188        let mut attrs = self.clone();
189        let mut last_off = cur + attrs.pos;
190        while let Some(attr) = attrs.next() {
191            let Ok(attr) = attr else { break };
192            match attr {
193                AssocDevInfo::Ifindex(val) => {
194                    if last_off == offset {
195                        stack.push(("Ifindex", last_off));
196                        break;
197                    }
198                }
199                AssocDevInfo::Nsid(val) => {
200                    if last_off == offset {
201                        stack.push(("Nsid", last_off));
202                        break;
203                    }
204                }
205                _ => {}
206            };
207            last_off = cur + attrs.pos;
208        }
209        if !stack.is_empty() {
210            stack.push(("AssocDevInfo", cur));
211        }
212        (stack, None)
213    }
214}
215#[derive(Clone)]
216pub enum Dev<'a> {
217    #[doc = "PSP device ID.\n"]
218    Id(u32),
219    #[doc = "ifindex of the main netdevice linked to the PSP device, or the ifindex\nto associate with the PSP device.\n"]
220    Ifindex(u32),
221    #[doc = "Bitmask of PSP versions supported by the device.\n\nAssociated type: [`Version`] (1 bit per enumeration)"]
222    PspVersionsCap(u32),
223    #[doc = "Bitmask of currently enabled (accepted on Rx) PSP versions.\n\nAssociated type: [`Version`] (1 bit per enumeration)"]
224    PspVersionsEna(u32),
225    #[doc = "List of associated virtual devices.\n\nAttribute may repeat multiple times (treat it as array)"]
226    AssocList(IterableAssocDevInfo<'a>),
227    #[doc = "Network namespace ID for the device to associate/disassociate. Optional\nfor dev-assoc and dev-disassoc; if not present, the device is looked up\nin the caller\\'s network namespace.\n"]
228    Nsid(i32),
229    #[doc = "Flag indicating the PSP device is an associated device from a different\nnetwork namespace. Present when in associated namespace, absent when in\nprimary/host namespace.\n"]
230    ByAssociation(()),
231}
232impl<'a> IterableDev<'a> {
233    #[doc = "PSP device ID.\n"]
234    pub fn get_id(&self) -> Result<u32, ErrorContext> {
235        let mut iter = self.clone();
236        iter.pos = 0;
237        for attr in iter {
238            if let Ok(Dev::Id(val)) = attr {
239                return Ok(val);
240            }
241        }
242        Err(ErrorContext::new_missing(
243            "Dev",
244            "Id",
245            self.orig_loc,
246            self.buf.as_ptr() as usize,
247        ))
248    }
249    #[doc = "ifindex of the main netdevice linked to the PSP device, or the ifindex\nto associate with the PSP device.\n"]
250    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
251        let mut iter = self.clone();
252        iter.pos = 0;
253        for attr in iter {
254            if let Ok(Dev::Ifindex(val)) = attr {
255                return Ok(val);
256            }
257        }
258        Err(ErrorContext::new_missing(
259            "Dev",
260            "Ifindex",
261            self.orig_loc,
262            self.buf.as_ptr() as usize,
263        ))
264    }
265    #[doc = "Bitmask of PSP versions supported by the device.\n\nAssociated type: [`Version`] (1 bit per enumeration)"]
266    pub fn get_psp_versions_cap(&self) -> Result<u32, ErrorContext> {
267        let mut iter = self.clone();
268        iter.pos = 0;
269        for attr in iter {
270            if let Ok(Dev::PspVersionsCap(val)) = attr {
271                return Ok(val);
272            }
273        }
274        Err(ErrorContext::new_missing(
275            "Dev",
276            "PspVersionsCap",
277            self.orig_loc,
278            self.buf.as_ptr() as usize,
279        ))
280    }
281    #[doc = "Bitmask of currently enabled (accepted on Rx) PSP versions.\n\nAssociated type: [`Version`] (1 bit per enumeration)"]
282    pub fn get_psp_versions_ena(&self) -> Result<u32, ErrorContext> {
283        let mut iter = self.clone();
284        iter.pos = 0;
285        for attr in iter {
286            if let Ok(Dev::PspVersionsEna(val)) = attr {
287                return Ok(val);
288            }
289        }
290        Err(ErrorContext::new_missing(
291            "Dev",
292            "PspVersionsEna",
293            self.orig_loc,
294            self.buf.as_ptr() as usize,
295        ))
296    }
297    #[doc = "List of associated virtual devices.\n\nAttribute may repeat multiple times (treat it as array)"]
298    pub fn get_assoc_list(&self) -> MultiAttrIterable<Self, Dev<'a>, IterableAssocDevInfo<'a>> {
299        MultiAttrIterable::new(self.clone(), |variant| {
300            if let Dev::AssocList(val) = variant {
301                Some(val)
302            } else {
303                None
304            }
305        })
306    }
307    #[doc = "Network namespace ID for the device to associate/disassociate. Optional\nfor dev-assoc and dev-disassoc; if not present, the device is looked up\nin the caller\\'s network namespace.\n"]
308    pub fn get_nsid(&self) -> Result<i32, ErrorContext> {
309        let mut iter = self.clone();
310        iter.pos = 0;
311        for attr in iter {
312            if let Ok(Dev::Nsid(val)) = attr {
313                return Ok(val);
314            }
315        }
316        Err(ErrorContext::new_missing(
317            "Dev",
318            "Nsid",
319            self.orig_loc,
320            self.buf.as_ptr() as usize,
321        ))
322    }
323    #[doc = "Flag indicating the PSP device is an associated device from a different\nnetwork namespace. Present when in associated namespace, absent when in\nprimary/host namespace.\n"]
324    pub fn get_by_association(&self) -> Result<(), ErrorContext> {
325        let mut iter = self.clone();
326        iter.pos = 0;
327        for attr in iter {
328            if let Ok(Dev::ByAssociation(val)) = attr {
329                return Ok(val);
330            }
331        }
332        Err(ErrorContext::new_missing(
333            "Dev",
334            "ByAssociation",
335            self.orig_loc,
336            self.buf.as_ptr() as usize,
337        ))
338    }
339}
340impl Dev<'_> {
341    pub fn new<'a>(buf: &'a [u8]) -> IterableDev<'a> {
342        IterableDev::with_loc(buf, buf.as_ptr() as usize)
343    }
344    fn attr_from_type(r#type: u16) -> Option<&'static str> {
345        let res = match r#type {
346            1u16 => "Id",
347            2u16 => "Ifindex",
348            3u16 => "PspVersionsCap",
349            4u16 => "PspVersionsEna",
350            5u16 => "AssocList",
351            6u16 => "Nsid",
352            7u16 => "ByAssociation",
353            _ => return None,
354        };
355        Some(res)
356    }
357}
358#[derive(Clone, Copy, Default)]
359pub struct IterableDev<'a> {
360    buf: &'a [u8],
361    pos: usize,
362    orig_loc: usize,
363}
364impl<'a> IterableDev<'a> {
365    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
366        Self {
367            buf,
368            pos: 0,
369            orig_loc,
370        }
371    }
372    pub fn get_buf(&self) -> &'a [u8] {
373        self.buf
374    }
375}
376impl<'a> Iterator for IterableDev<'a> {
377    type Item = Result<Dev<'a>, ErrorContext>;
378    fn next(&mut self) -> Option<Self::Item> {
379        let mut pos;
380        let mut r#type;
381        loop {
382            pos = self.pos;
383            r#type = None;
384            if self.buf.len() == self.pos {
385                return None;
386            }
387            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
388                self.pos = self.buf.len();
389                break;
390            };
391            r#type = Some(header.r#type);
392            let res = match header.r#type {
393                1u16 => Dev::Id({
394                    let res = parse_u32(next);
395                    let Some(val) = res else { break };
396                    val
397                }),
398                2u16 => Dev::Ifindex({
399                    let res = parse_u32(next);
400                    let Some(val) = res else { break };
401                    val
402                }),
403                3u16 => Dev::PspVersionsCap({
404                    let res = parse_u32(next);
405                    let Some(val) = res else { break };
406                    val
407                }),
408                4u16 => Dev::PspVersionsEna({
409                    let res = parse_u32(next);
410                    let Some(val) = res else { break };
411                    val
412                }),
413                5u16 => Dev::AssocList({
414                    let res = Some(IterableAssocDevInfo::with_loc(next, self.orig_loc));
415                    let Some(val) = res else { break };
416                    val
417                }),
418                6u16 => Dev::Nsid({
419                    let res = parse_i32(next);
420                    let Some(val) = res else { break };
421                    val
422                }),
423                7u16 => Dev::ByAssociation(()),
424                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
425                n => continue,
426            };
427            return Some(Ok(res));
428        }
429        Some(Err(ErrorContext::new(
430            "Dev",
431            r#type.and_then(|t| Dev::attr_from_type(t)),
432            self.orig_loc,
433            self.buf.as_ptr().wrapping_add(pos) as usize,
434        )))
435    }
436}
437impl<'a> std::fmt::Debug for IterableDev<'_> {
438    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
439        let mut fmt = f.debug_struct("Dev");
440        for attr in self.clone() {
441            let attr = match attr {
442                Ok(a) => a,
443                Err(err) => {
444                    fmt.finish()?;
445                    f.write_str("Err(")?;
446                    err.fmt(f)?;
447                    return f.write_str(")");
448                }
449            };
450            match attr {
451                Dev::Id(val) => fmt.field("Id", &val),
452                Dev::Ifindex(val) => fmt.field("Ifindex", &val),
453                Dev::PspVersionsCap(val) => fmt.field(
454                    "PspVersionsCap",
455                    &FormatFlags(val.into(), |val| {
456                        Version::from_value(val.trailing_zeros().into())
457                    }),
458                ),
459                Dev::PspVersionsEna(val) => fmt.field(
460                    "PspVersionsEna",
461                    &FormatFlags(val.into(), |val| {
462                        Version::from_value(val.trailing_zeros().into())
463                    }),
464                ),
465                Dev::AssocList(val) => fmt.field("AssocList", &val),
466                Dev::Nsid(val) => fmt.field("Nsid", &val),
467                Dev::ByAssociation(val) => fmt.field("ByAssociation", &val),
468            };
469        }
470        fmt.finish()
471    }
472}
473impl IterableDev<'_> {
474    pub fn lookup_attr(
475        &self,
476        offset: usize,
477        missing_type: Option<u16>,
478    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
479        let mut stack = Vec::new();
480        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
481        if missing_type.is_some() && cur == offset {
482            stack.push(("Dev", offset));
483            return (stack, missing_type.and_then(|t| Dev::attr_from_type(t)));
484        }
485        if cur > offset || cur + self.buf.len() < offset {
486            return (stack, None);
487        }
488        let mut attrs = self.clone();
489        let mut last_off = cur + attrs.pos;
490        let mut missing = None;
491        while let Some(attr) = attrs.next() {
492            let Ok(attr) = attr else { break };
493            match attr {
494                Dev::Id(val) => {
495                    if last_off == offset {
496                        stack.push(("Id", last_off));
497                        break;
498                    }
499                }
500                Dev::Ifindex(val) => {
501                    if last_off == offset {
502                        stack.push(("Ifindex", last_off));
503                        break;
504                    }
505                }
506                Dev::PspVersionsCap(val) => {
507                    if last_off == offset {
508                        stack.push(("PspVersionsCap", last_off));
509                        break;
510                    }
511                }
512                Dev::PspVersionsEna(val) => {
513                    if last_off == offset {
514                        stack.push(("PspVersionsEna", last_off));
515                        break;
516                    }
517                }
518                Dev::AssocList(val) => {
519                    (stack, missing) = val.lookup_attr(offset, missing_type);
520                    if !stack.is_empty() {
521                        break;
522                    }
523                }
524                Dev::Nsid(val) => {
525                    if last_off == offset {
526                        stack.push(("Nsid", last_off));
527                        break;
528                    }
529                }
530                Dev::ByAssociation(val) => {
531                    if last_off == offset {
532                        stack.push(("ByAssociation", last_off));
533                        break;
534                    }
535                }
536                _ => {}
537            };
538            last_off = cur + attrs.pos;
539        }
540        if !stack.is_empty() {
541            stack.push(("Dev", cur));
542        }
543        (stack, missing)
544    }
545}
546#[derive(Clone)]
547pub enum Assoc<'a> {
548    #[doc = "PSP device ID.\n"]
549    DevId(u32),
550    #[doc = "PSP versions (AEAD and protocol version) used by this association,\ndictates the size of the key.\n\nAssociated type: [`Version`] (enum)"]
551    Version(u32),
552    RxKey(IterableKeys<'a>),
553    TxKey(IterableKeys<'a>),
554    #[doc = "Sockets which should be bound to the association immediately.\n"]
555    SockFd(u32),
556}
557impl<'a> IterableAssoc<'a> {
558    #[doc = "PSP device ID.\n"]
559    pub fn get_dev_id(&self) -> Result<u32, ErrorContext> {
560        let mut iter = self.clone();
561        iter.pos = 0;
562        for attr in iter {
563            if let Ok(Assoc::DevId(val)) = attr {
564                return Ok(val);
565            }
566        }
567        Err(ErrorContext::new_missing(
568            "Assoc",
569            "DevId",
570            self.orig_loc,
571            self.buf.as_ptr() as usize,
572        ))
573    }
574    #[doc = "PSP versions (AEAD and protocol version) used by this association,\ndictates the size of the key.\n\nAssociated type: [`Version`] (enum)"]
575    pub fn get_version(&self) -> Result<u32, ErrorContext> {
576        let mut iter = self.clone();
577        iter.pos = 0;
578        for attr in iter {
579            if let Ok(Assoc::Version(val)) = attr {
580                return Ok(val);
581            }
582        }
583        Err(ErrorContext::new_missing(
584            "Assoc",
585            "Version",
586            self.orig_loc,
587            self.buf.as_ptr() as usize,
588        ))
589    }
590    pub fn get_rx_key(&self) -> Result<IterableKeys<'a>, ErrorContext> {
591        let mut iter = self.clone();
592        iter.pos = 0;
593        for attr in iter {
594            if let Ok(Assoc::RxKey(val)) = attr {
595                return Ok(val);
596            }
597        }
598        Err(ErrorContext::new_missing(
599            "Assoc",
600            "RxKey",
601            self.orig_loc,
602            self.buf.as_ptr() as usize,
603        ))
604    }
605    pub fn get_tx_key(&self) -> Result<IterableKeys<'a>, ErrorContext> {
606        let mut iter = self.clone();
607        iter.pos = 0;
608        for attr in iter {
609            if let Ok(Assoc::TxKey(val)) = attr {
610                return Ok(val);
611            }
612        }
613        Err(ErrorContext::new_missing(
614            "Assoc",
615            "TxKey",
616            self.orig_loc,
617            self.buf.as_ptr() as usize,
618        ))
619    }
620    #[doc = "Sockets which should be bound to the association immediately.\n"]
621    pub fn get_sock_fd(&self) -> Result<u32, ErrorContext> {
622        let mut iter = self.clone();
623        iter.pos = 0;
624        for attr in iter {
625            if let Ok(Assoc::SockFd(val)) = attr {
626                return Ok(val);
627            }
628        }
629        Err(ErrorContext::new_missing(
630            "Assoc",
631            "SockFd",
632            self.orig_loc,
633            self.buf.as_ptr() as usize,
634        ))
635    }
636}
637impl Assoc<'_> {
638    pub fn new<'a>(buf: &'a [u8]) -> IterableAssoc<'a> {
639        IterableAssoc::with_loc(buf, buf.as_ptr() as usize)
640    }
641    fn attr_from_type(r#type: u16) -> Option<&'static str> {
642        let res = match r#type {
643            1u16 => "DevId",
644            2u16 => "Version",
645            3u16 => "RxKey",
646            4u16 => "TxKey",
647            5u16 => "SockFd",
648            _ => return None,
649        };
650        Some(res)
651    }
652}
653#[derive(Clone, Copy, Default)]
654pub struct IterableAssoc<'a> {
655    buf: &'a [u8],
656    pos: usize,
657    orig_loc: usize,
658}
659impl<'a> IterableAssoc<'a> {
660    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
661        Self {
662            buf,
663            pos: 0,
664            orig_loc,
665        }
666    }
667    pub fn get_buf(&self) -> &'a [u8] {
668        self.buf
669    }
670}
671impl<'a> Iterator for IterableAssoc<'a> {
672    type Item = Result<Assoc<'a>, ErrorContext>;
673    fn next(&mut self) -> Option<Self::Item> {
674        let mut pos;
675        let mut r#type;
676        loop {
677            pos = self.pos;
678            r#type = None;
679            if self.buf.len() == self.pos {
680                return None;
681            }
682            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
683                self.pos = self.buf.len();
684                break;
685            };
686            r#type = Some(header.r#type);
687            let res = match header.r#type {
688                1u16 => Assoc::DevId({
689                    let res = parse_u32(next);
690                    let Some(val) = res else { break };
691                    val
692                }),
693                2u16 => Assoc::Version({
694                    let res = parse_u32(next);
695                    let Some(val) = res else { break };
696                    val
697                }),
698                3u16 => Assoc::RxKey({
699                    let res = Some(IterableKeys::with_loc(next, self.orig_loc));
700                    let Some(val) = res else { break };
701                    val
702                }),
703                4u16 => Assoc::TxKey({
704                    let res = Some(IterableKeys::with_loc(next, self.orig_loc));
705                    let Some(val) = res else { break };
706                    val
707                }),
708                5u16 => Assoc::SockFd({
709                    let res = parse_u32(next);
710                    let Some(val) = res else { break };
711                    val
712                }),
713                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
714                n => continue,
715            };
716            return Some(Ok(res));
717        }
718        Some(Err(ErrorContext::new(
719            "Assoc",
720            r#type.and_then(|t| Assoc::attr_from_type(t)),
721            self.orig_loc,
722            self.buf.as_ptr().wrapping_add(pos) as usize,
723        )))
724    }
725}
726impl<'a> std::fmt::Debug for IterableAssoc<'_> {
727    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
728        let mut fmt = f.debug_struct("Assoc");
729        for attr in self.clone() {
730            let attr = match attr {
731                Ok(a) => a,
732                Err(err) => {
733                    fmt.finish()?;
734                    f.write_str("Err(")?;
735                    err.fmt(f)?;
736                    return f.write_str(")");
737                }
738            };
739            match attr {
740                Assoc::DevId(val) => fmt.field("DevId", &val),
741                Assoc::Version(val) => {
742                    fmt.field("Version", &FormatEnum(val.into(), Version::from_value))
743                }
744                Assoc::RxKey(val) => fmt.field("RxKey", &val),
745                Assoc::TxKey(val) => fmt.field("TxKey", &val),
746                Assoc::SockFd(val) => fmt.field("SockFd", &val),
747            };
748        }
749        fmt.finish()
750    }
751}
752impl IterableAssoc<'_> {
753    pub fn lookup_attr(
754        &self,
755        offset: usize,
756        missing_type: Option<u16>,
757    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
758        let mut stack = Vec::new();
759        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
760        if missing_type.is_some() && cur == offset {
761            stack.push(("Assoc", offset));
762            return (stack, missing_type.and_then(|t| Assoc::attr_from_type(t)));
763        }
764        if cur > offset || cur + self.buf.len() < offset {
765            return (stack, None);
766        }
767        let mut attrs = self.clone();
768        let mut last_off = cur + attrs.pos;
769        let mut missing = None;
770        while let Some(attr) = attrs.next() {
771            let Ok(attr) = attr else { break };
772            match attr {
773                Assoc::DevId(val) => {
774                    if last_off == offset {
775                        stack.push(("DevId", last_off));
776                        break;
777                    }
778                }
779                Assoc::Version(val) => {
780                    if last_off == offset {
781                        stack.push(("Version", last_off));
782                        break;
783                    }
784                }
785                Assoc::RxKey(val) => {
786                    (stack, missing) = val.lookup_attr(offset, missing_type);
787                    if !stack.is_empty() {
788                        break;
789                    }
790                }
791                Assoc::TxKey(val) => {
792                    (stack, missing) = val.lookup_attr(offset, missing_type);
793                    if !stack.is_empty() {
794                        break;
795                    }
796                }
797                Assoc::SockFd(val) => {
798                    if last_off == offset {
799                        stack.push(("SockFd", last_off));
800                        break;
801                    }
802                }
803                _ => {}
804            };
805            last_off = cur + attrs.pos;
806        }
807        if !stack.is_empty() {
808            stack.push(("Assoc", cur));
809        }
810        (stack, missing)
811    }
812}
813#[derive(Clone)]
814pub enum Keys<'a> {
815    Key(&'a [u8]),
816    #[doc = "Security Parameters Index (SPI) of the association.\n"]
817    Spi(u32),
818}
819impl<'a> IterableKeys<'a> {
820    pub fn get_key(&self) -> Result<&'a [u8], ErrorContext> {
821        let mut iter = self.clone();
822        iter.pos = 0;
823        for attr in iter {
824            if let Ok(Keys::Key(val)) = attr {
825                return Ok(val);
826            }
827        }
828        Err(ErrorContext::new_missing(
829            "Keys",
830            "Key",
831            self.orig_loc,
832            self.buf.as_ptr() as usize,
833        ))
834    }
835    #[doc = "Security Parameters Index (SPI) of the association.\n"]
836    pub fn get_spi(&self) -> Result<u32, ErrorContext> {
837        let mut iter = self.clone();
838        iter.pos = 0;
839        for attr in iter {
840            if let Ok(Keys::Spi(val)) = attr {
841                return Ok(val);
842            }
843        }
844        Err(ErrorContext::new_missing(
845            "Keys",
846            "Spi",
847            self.orig_loc,
848            self.buf.as_ptr() as usize,
849        ))
850    }
851}
852impl Keys<'_> {
853    pub fn new<'a>(buf: &'a [u8]) -> IterableKeys<'a> {
854        IterableKeys::with_loc(buf, buf.as_ptr() as usize)
855    }
856    fn attr_from_type(r#type: u16) -> Option<&'static str> {
857        let res = match r#type {
858            1u16 => "Key",
859            2u16 => "Spi",
860            _ => return None,
861        };
862        Some(res)
863    }
864}
865#[derive(Clone, Copy, Default)]
866pub struct IterableKeys<'a> {
867    buf: &'a [u8],
868    pos: usize,
869    orig_loc: usize,
870}
871impl<'a> IterableKeys<'a> {
872    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
873        Self {
874            buf,
875            pos: 0,
876            orig_loc,
877        }
878    }
879    pub fn get_buf(&self) -> &'a [u8] {
880        self.buf
881    }
882}
883impl<'a> Iterator for IterableKeys<'a> {
884    type Item = Result<Keys<'a>, ErrorContext>;
885    fn next(&mut self) -> Option<Self::Item> {
886        let mut pos;
887        let mut r#type;
888        loop {
889            pos = self.pos;
890            r#type = None;
891            if self.buf.len() == self.pos {
892                return None;
893            }
894            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
895                self.pos = self.buf.len();
896                break;
897            };
898            r#type = Some(header.r#type);
899            let res = match header.r#type {
900                1u16 => Keys::Key({
901                    let res = Some(next);
902                    let Some(val) = res else { break };
903                    val
904                }),
905                2u16 => Keys::Spi({
906                    let res = parse_u32(next);
907                    let Some(val) = res else { break };
908                    val
909                }),
910                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
911                n => continue,
912            };
913            return Some(Ok(res));
914        }
915        Some(Err(ErrorContext::new(
916            "Keys",
917            r#type.and_then(|t| Keys::attr_from_type(t)),
918            self.orig_loc,
919            self.buf.as_ptr().wrapping_add(pos) as usize,
920        )))
921    }
922}
923impl<'a> std::fmt::Debug for IterableKeys<'_> {
924    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
925        let mut fmt = f.debug_struct("Keys");
926        for attr in self.clone() {
927            let attr = match attr {
928                Ok(a) => a,
929                Err(err) => {
930                    fmt.finish()?;
931                    f.write_str("Err(")?;
932                    err.fmt(f)?;
933                    return f.write_str(")");
934                }
935            };
936            match attr {
937                Keys::Key(val) => fmt.field("Key", &val),
938                Keys::Spi(val) => fmt.field("Spi", &val),
939            };
940        }
941        fmt.finish()
942    }
943}
944impl IterableKeys<'_> {
945    pub fn lookup_attr(
946        &self,
947        offset: usize,
948        missing_type: Option<u16>,
949    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
950        let mut stack = Vec::new();
951        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
952        if missing_type.is_some() && cur == offset {
953            stack.push(("Keys", offset));
954            return (stack, missing_type.and_then(|t| Keys::attr_from_type(t)));
955        }
956        if cur > offset || cur + self.buf.len() < offset {
957            return (stack, None);
958        }
959        let mut attrs = self.clone();
960        let mut last_off = cur + attrs.pos;
961        while let Some(attr) = attrs.next() {
962            let Ok(attr) = attr else { break };
963            match attr {
964                Keys::Key(val) => {
965                    if last_off == offset {
966                        stack.push(("Key", last_off));
967                        break;
968                    }
969                }
970                Keys::Spi(val) => {
971                    if last_off == offset {
972                        stack.push(("Spi", last_off));
973                        break;
974                    }
975                }
976                _ => {}
977            };
978            last_off = cur + attrs.pos;
979        }
980        if !stack.is_empty() {
981            stack.push(("Keys", cur));
982        }
983        (stack, None)
984    }
985}
986#[derive(Clone)]
987pub enum Stats {
988    #[doc = "PSP device ID.\n"]
989    DevId(u32),
990    #[doc = "Number of key rotations during the lifetime of the device. Kernel\nstatistic.\n"]
991    KeyRotations(u32),
992    #[doc = "Number of times a socket\\'s Rx got shut down due to using a key which\nwent stale (fully rotated out). Kernel statistic.\n"]
993    StaleEvents(u32),
994    #[doc = "Number of successfully processed and authenticated PSP packets. Device\nstatistic (from the PSP spec).\n"]
995    RxPackets(u32),
996    #[doc = "Number of successfully authenticated PSP bytes received, counting from\nthe first byte after the IV through the last byte of payload. The fixed\ninitial portion of the PSP header (16 bytes) and the PSP trailer/ICV (16\nbytes) are not included in this count. Device statistic (from the PSP\nspec).\n"]
997    RxBytes(u32),
998    #[doc = "Number of received PSP packets with unsuccessful authentication. Device\nstatistic (from the PSP spec).\n"]
999    RxAuthFail(u32),
1000    #[doc = "Number of received PSP packets with length/framing errors. Device\nstatistic (from the PSP spec).\n"]
1001    RxError(u32),
1002    #[doc = "Number of received PSP packets with miscellaneous errors (invalid master\nkey indicated by SPI, unsupported version, etc.) Device statistic (from\nthe PSP spec).\n"]
1003    RxBad(u32),
1004    #[doc = "Number of successfully processed PSP packets for transmission. Device\nstatistic (from the PSP spec).\n"]
1005    TxPackets(u32),
1006    #[doc = "Number of successfully processed PSP bytes for transmit, counting from\nthe first byte after the IV through the last byte of payload. The fixed\ninitial portion of the PSP header (16 bytes) and the PSP trailer/ICV (16\nbytes) are not included in this count. Device statistic (from the PSP\nspec).\n"]
1007    TxBytes(u32),
1008    #[doc = "Number of PSP packets for transmission with errors. Device statistic\n(from the PSP spec).\n"]
1009    TxError(u32),
1010}
1011impl<'a> IterableStats<'a> {
1012    #[doc = "PSP device ID.\n"]
1013    pub fn get_dev_id(&self) -> Result<u32, ErrorContext> {
1014        let mut iter = self.clone();
1015        iter.pos = 0;
1016        for attr in iter {
1017            if let Ok(Stats::DevId(val)) = attr {
1018                return Ok(val);
1019            }
1020        }
1021        Err(ErrorContext::new_missing(
1022            "Stats",
1023            "DevId",
1024            self.orig_loc,
1025            self.buf.as_ptr() as usize,
1026        ))
1027    }
1028    #[doc = "Number of key rotations during the lifetime of the device. Kernel\nstatistic.\n"]
1029    pub fn get_key_rotations(&self) -> Result<u32, ErrorContext> {
1030        let mut iter = self.clone();
1031        iter.pos = 0;
1032        for attr in iter {
1033            if let Ok(Stats::KeyRotations(val)) = attr {
1034                return Ok(val);
1035            }
1036        }
1037        Err(ErrorContext::new_missing(
1038            "Stats",
1039            "KeyRotations",
1040            self.orig_loc,
1041            self.buf.as_ptr() as usize,
1042        ))
1043    }
1044    #[doc = "Number of times a socket\\'s Rx got shut down due to using a key which\nwent stale (fully rotated out). Kernel statistic.\n"]
1045    pub fn get_stale_events(&self) -> Result<u32, ErrorContext> {
1046        let mut iter = self.clone();
1047        iter.pos = 0;
1048        for attr in iter {
1049            if let Ok(Stats::StaleEvents(val)) = attr {
1050                return Ok(val);
1051            }
1052        }
1053        Err(ErrorContext::new_missing(
1054            "Stats",
1055            "StaleEvents",
1056            self.orig_loc,
1057            self.buf.as_ptr() as usize,
1058        ))
1059    }
1060    #[doc = "Number of successfully processed and authenticated PSP packets. Device\nstatistic (from the PSP spec).\n"]
1061    pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
1062        let mut iter = self.clone();
1063        iter.pos = 0;
1064        for attr in iter {
1065            if let Ok(Stats::RxPackets(val)) = attr {
1066                return Ok(val);
1067            }
1068        }
1069        Err(ErrorContext::new_missing(
1070            "Stats",
1071            "RxPackets",
1072            self.orig_loc,
1073            self.buf.as_ptr() as usize,
1074        ))
1075    }
1076    #[doc = "Number of successfully authenticated PSP bytes received, counting from\nthe first byte after the IV through the last byte of payload. The fixed\ninitial portion of the PSP header (16 bytes) and the PSP trailer/ICV (16\nbytes) are not included in this count. Device statistic (from the PSP\nspec).\n"]
1077    pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
1078        let mut iter = self.clone();
1079        iter.pos = 0;
1080        for attr in iter {
1081            if let Ok(Stats::RxBytes(val)) = attr {
1082                return Ok(val);
1083            }
1084        }
1085        Err(ErrorContext::new_missing(
1086            "Stats",
1087            "RxBytes",
1088            self.orig_loc,
1089            self.buf.as_ptr() as usize,
1090        ))
1091    }
1092    #[doc = "Number of received PSP packets with unsuccessful authentication. Device\nstatistic (from the PSP spec).\n"]
1093    pub fn get_rx_auth_fail(&self) -> Result<u32, ErrorContext> {
1094        let mut iter = self.clone();
1095        iter.pos = 0;
1096        for attr in iter {
1097            if let Ok(Stats::RxAuthFail(val)) = attr {
1098                return Ok(val);
1099            }
1100        }
1101        Err(ErrorContext::new_missing(
1102            "Stats",
1103            "RxAuthFail",
1104            self.orig_loc,
1105            self.buf.as_ptr() as usize,
1106        ))
1107    }
1108    #[doc = "Number of received PSP packets with length/framing errors. Device\nstatistic (from the PSP spec).\n"]
1109    pub fn get_rx_error(&self) -> Result<u32, ErrorContext> {
1110        let mut iter = self.clone();
1111        iter.pos = 0;
1112        for attr in iter {
1113            if let Ok(Stats::RxError(val)) = attr {
1114                return Ok(val);
1115            }
1116        }
1117        Err(ErrorContext::new_missing(
1118            "Stats",
1119            "RxError",
1120            self.orig_loc,
1121            self.buf.as_ptr() as usize,
1122        ))
1123    }
1124    #[doc = "Number of received PSP packets with miscellaneous errors (invalid master\nkey indicated by SPI, unsupported version, etc.) Device statistic (from\nthe PSP spec).\n"]
1125    pub fn get_rx_bad(&self) -> Result<u32, ErrorContext> {
1126        let mut iter = self.clone();
1127        iter.pos = 0;
1128        for attr in iter {
1129            if let Ok(Stats::RxBad(val)) = attr {
1130                return Ok(val);
1131            }
1132        }
1133        Err(ErrorContext::new_missing(
1134            "Stats",
1135            "RxBad",
1136            self.orig_loc,
1137            self.buf.as_ptr() as usize,
1138        ))
1139    }
1140    #[doc = "Number of successfully processed PSP packets for transmission. Device\nstatistic (from the PSP spec).\n"]
1141    pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
1142        let mut iter = self.clone();
1143        iter.pos = 0;
1144        for attr in iter {
1145            if let Ok(Stats::TxPackets(val)) = attr {
1146                return Ok(val);
1147            }
1148        }
1149        Err(ErrorContext::new_missing(
1150            "Stats",
1151            "TxPackets",
1152            self.orig_loc,
1153            self.buf.as_ptr() as usize,
1154        ))
1155    }
1156    #[doc = "Number of successfully processed PSP bytes for transmit, counting from\nthe first byte after the IV through the last byte of payload. The fixed\ninitial portion of the PSP header (16 bytes) and the PSP trailer/ICV (16\nbytes) are not included in this count. Device statistic (from the PSP\nspec).\n"]
1157    pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
1158        let mut iter = self.clone();
1159        iter.pos = 0;
1160        for attr in iter {
1161            if let Ok(Stats::TxBytes(val)) = attr {
1162                return Ok(val);
1163            }
1164        }
1165        Err(ErrorContext::new_missing(
1166            "Stats",
1167            "TxBytes",
1168            self.orig_loc,
1169            self.buf.as_ptr() as usize,
1170        ))
1171    }
1172    #[doc = "Number of PSP packets for transmission with errors. Device statistic\n(from the PSP spec).\n"]
1173    pub fn get_tx_error(&self) -> Result<u32, ErrorContext> {
1174        let mut iter = self.clone();
1175        iter.pos = 0;
1176        for attr in iter {
1177            if let Ok(Stats::TxError(val)) = attr {
1178                return Ok(val);
1179            }
1180        }
1181        Err(ErrorContext::new_missing(
1182            "Stats",
1183            "TxError",
1184            self.orig_loc,
1185            self.buf.as_ptr() as usize,
1186        ))
1187    }
1188}
1189impl Stats {
1190    pub fn new<'a>(buf: &'a [u8]) -> IterableStats<'a> {
1191        IterableStats::with_loc(buf, buf.as_ptr() as usize)
1192    }
1193    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1194        let res = match r#type {
1195            1u16 => "DevId",
1196            2u16 => "KeyRotations",
1197            3u16 => "StaleEvents",
1198            4u16 => "RxPackets",
1199            5u16 => "RxBytes",
1200            6u16 => "RxAuthFail",
1201            7u16 => "RxError",
1202            8u16 => "RxBad",
1203            9u16 => "TxPackets",
1204            10u16 => "TxBytes",
1205            11u16 => "TxError",
1206            _ => return None,
1207        };
1208        Some(res)
1209    }
1210}
1211#[derive(Clone, Copy, Default)]
1212pub struct IterableStats<'a> {
1213    buf: &'a [u8],
1214    pos: usize,
1215    orig_loc: usize,
1216}
1217impl<'a> IterableStats<'a> {
1218    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1219        Self {
1220            buf,
1221            pos: 0,
1222            orig_loc,
1223        }
1224    }
1225    pub fn get_buf(&self) -> &'a [u8] {
1226        self.buf
1227    }
1228}
1229impl<'a> Iterator for IterableStats<'a> {
1230    type Item = Result<Stats, ErrorContext>;
1231    fn next(&mut self) -> Option<Self::Item> {
1232        let mut pos;
1233        let mut r#type;
1234        loop {
1235            pos = self.pos;
1236            r#type = None;
1237            if self.buf.len() == self.pos {
1238                return None;
1239            }
1240            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1241                self.pos = self.buf.len();
1242                break;
1243            };
1244            r#type = Some(header.r#type);
1245            let res = match header.r#type {
1246                1u16 => Stats::DevId({
1247                    let res = parse_u32(next);
1248                    let Some(val) = res else { break };
1249                    val
1250                }),
1251                2u16 => Stats::KeyRotations({
1252                    let res = parse_u32(next);
1253                    let Some(val) = res else { break };
1254                    val
1255                }),
1256                3u16 => Stats::StaleEvents({
1257                    let res = parse_u32(next);
1258                    let Some(val) = res else { break };
1259                    val
1260                }),
1261                4u16 => Stats::RxPackets({
1262                    let res = parse_u32(next);
1263                    let Some(val) = res else { break };
1264                    val
1265                }),
1266                5u16 => Stats::RxBytes({
1267                    let res = parse_u32(next);
1268                    let Some(val) = res else { break };
1269                    val
1270                }),
1271                6u16 => Stats::RxAuthFail({
1272                    let res = parse_u32(next);
1273                    let Some(val) = res else { break };
1274                    val
1275                }),
1276                7u16 => Stats::RxError({
1277                    let res = parse_u32(next);
1278                    let Some(val) = res else { break };
1279                    val
1280                }),
1281                8u16 => Stats::RxBad({
1282                    let res = parse_u32(next);
1283                    let Some(val) = res else { break };
1284                    val
1285                }),
1286                9u16 => Stats::TxPackets({
1287                    let res = parse_u32(next);
1288                    let Some(val) = res else { break };
1289                    val
1290                }),
1291                10u16 => Stats::TxBytes({
1292                    let res = parse_u32(next);
1293                    let Some(val) = res else { break };
1294                    val
1295                }),
1296                11u16 => Stats::TxError({
1297                    let res = parse_u32(next);
1298                    let Some(val) = res else { break };
1299                    val
1300                }),
1301                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1302                n => continue,
1303            };
1304            return Some(Ok(res));
1305        }
1306        Some(Err(ErrorContext::new(
1307            "Stats",
1308            r#type.and_then(|t| Stats::attr_from_type(t)),
1309            self.orig_loc,
1310            self.buf.as_ptr().wrapping_add(pos) as usize,
1311        )))
1312    }
1313}
1314impl std::fmt::Debug for IterableStats<'_> {
1315    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1316        let mut fmt = f.debug_struct("Stats");
1317        for attr in self.clone() {
1318            let attr = match attr {
1319                Ok(a) => a,
1320                Err(err) => {
1321                    fmt.finish()?;
1322                    f.write_str("Err(")?;
1323                    err.fmt(f)?;
1324                    return f.write_str(")");
1325                }
1326            };
1327            match attr {
1328                Stats::DevId(val) => fmt.field("DevId", &val),
1329                Stats::KeyRotations(val) => fmt.field("KeyRotations", &val),
1330                Stats::StaleEvents(val) => fmt.field("StaleEvents", &val),
1331                Stats::RxPackets(val) => fmt.field("RxPackets", &val),
1332                Stats::RxBytes(val) => fmt.field("RxBytes", &val),
1333                Stats::RxAuthFail(val) => fmt.field("RxAuthFail", &val),
1334                Stats::RxError(val) => fmt.field("RxError", &val),
1335                Stats::RxBad(val) => fmt.field("RxBad", &val),
1336                Stats::TxPackets(val) => fmt.field("TxPackets", &val),
1337                Stats::TxBytes(val) => fmt.field("TxBytes", &val),
1338                Stats::TxError(val) => fmt.field("TxError", &val),
1339            };
1340        }
1341        fmt.finish()
1342    }
1343}
1344impl IterableStats<'_> {
1345    pub fn lookup_attr(
1346        &self,
1347        offset: usize,
1348        missing_type: Option<u16>,
1349    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1350        let mut stack = Vec::new();
1351        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1352        if missing_type.is_some() && cur == offset {
1353            stack.push(("Stats", offset));
1354            return (stack, missing_type.and_then(|t| Stats::attr_from_type(t)));
1355        }
1356        if cur > offset || cur + self.buf.len() < offset {
1357            return (stack, None);
1358        }
1359        let mut attrs = self.clone();
1360        let mut last_off = cur + attrs.pos;
1361        while let Some(attr) = attrs.next() {
1362            let Ok(attr) = attr else { break };
1363            match attr {
1364                Stats::DevId(val) => {
1365                    if last_off == offset {
1366                        stack.push(("DevId", last_off));
1367                        break;
1368                    }
1369                }
1370                Stats::KeyRotations(val) => {
1371                    if last_off == offset {
1372                        stack.push(("KeyRotations", last_off));
1373                        break;
1374                    }
1375                }
1376                Stats::StaleEvents(val) => {
1377                    if last_off == offset {
1378                        stack.push(("StaleEvents", last_off));
1379                        break;
1380                    }
1381                }
1382                Stats::RxPackets(val) => {
1383                    if last_off == offset {
1384                        stack.push(("RxPackets", last_off));
1385                        break;
1386                    }
1387                }
1388                Stats::RxBytes(val) => {
1389                    if last_off == offset {
1390                        stack.push(("RxBytes", last_off));
1391                        break;
1392                    }
1393                }
1394                Stats::RxAuthFail(val) => {
1395                    if last_off == offset {
1396                        stack.push(("RxAuthFail", last_off));
1397                        break;
1398                    }
1399                }
1400                Stats::RxError(val) => {
1401                    if last_off == offset {
1402                        stack.push(("RxError", last_off));
1403                        break;
1404                    }
1405                }
1406                Stats::RxBad(val) => {
1407                    if last_off == offset {
1408                        stack.push(("RxBad", last_off));
1409                        break;
1410                    }
1411                }
1412                Stats::TxPackets(val) => {
1413                    if last_off == offset {
1414                        stack.push(("TxPackets", last_off));
1415                        break;
1416                    }
1417                }
1418                Stats::TxBytes(val) => {
1419                    if last_off == offset {
1420                        stack.push(("TxBytes", last_off));
1421                        break;
1422                    }
1423                }
1424                Stats::TxError(val) => {
1425                    if last_off == offset {
1426                        stack.push(("TxError", last_off));
1427                        break;
1428                    }
1429                }
1430                _ => {}
1431            };
1432            last_off = cur + attrs.pos;
1433        }
1434        if !stack.is_empty() {
1435            stack.push(("Stats", cur));
1436        }
1437        (stack, None)
1438    }
1439}
1440pub struct PushAssocDevInfo<Prev: Pusher> {
1441    pub(crate) prev: Option<Prev>,
1442    pub(crate) header_offset: Option<usize>,
1443}
1444impl<Prev: Pusher> Pusher for PushAssocDevInfo<Prev> {
1445    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1446        self.prev.as_mut().unwrap().as_vec_mut()
1447    }
1448    fn as_vec(&self) -> &Vec<u8> {
1449        self.prev.as_ref().unwrap().as_vec()
1450    }
1451}
1452impl<Prev: Pusher> PushAssocDevInfo<Prev> {
1453    pub fn new(prev: Prev) -> Self {
1454        Self {
1455            prev: Some(prev),
1456            header_offset: None,
1457        }
1458    }
1459    pub fn end_nested(mut self) -> Prev {
1460        let mut prev = self.prev.take().unwrap();
1461        if let Some(header_offset) = &self.header_offset {
1462            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1463        }
1464        prev
1465    }
1466    #[doc = "ifindex of an associated network device.\n"]
1467    pub fn push_ifindex(mut self, value: u32) -> Self {
1468        push_header(self.as_vec_mut(), 1u16, 4 as u16);
1469        self.as_vec_mut().extend(value.to_ne_bytes());
1470        self
1471    }
1472    #[doc = "Network namespace ID of the associated device.\n"]
1473    pub fn push_nsid(mut self, value: i32) -> Self {
1474        push_header(self.as_vec_mut(), 2u16, 4 as u16);
1475        self.as_vec_mut().extend(value.to_ne_bytes());
1476        self
1477    }
1478}
1479impl<Prev: Pusher> Drop for PushAssocDevInfo<Prev> {
1480    fn drop(&mut self) {
1481        if let Some(prev) = &mut self.prev {
1482            if let Some(header_offset) = &self.header_offset {
1483                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1484            }
1485        }
1486    }
1487}
1488pub struct PushDev<Prev: Pusher> {
1489    pub(crate) prev: Option<Prev>,
1490    pub(crate) header_offset: Option<usize>,
1491}
1492impl<Prev: Pusher> Pusher for PushDev<Prev> {
1493    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1494        self.prev.as_mut().unwrap().as_vec_mut()
1495    }
1496    fn as_vec(&self) -> &Vec<u8> {
1497        self.prev.as_ref().unwrap().as_vec()
1498    }
1499}
1500impl<Prev: Pusher> PushDev<Prev> {
1501    pub fn new(prev: Prev) -> Self {
1502        Self {
1503            prev: Some(prev),
1504            header_offset: None,
1505        }
1506    }
1507    pub fn end_nested(mut self) -> Prev {
1508        let mut prev = self.prev.take().unwrap();
1509        if let Some(header_offset) = &self.header_offset {
1510            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1511        }
1512        prev
1513    }
1514    #[doc = "PSP device ID.\n"]
1515    pub fn push_id(mut self, value: u32) -> Self {
1516        push_header(self.as_vec_mut(), 1u16, 4 as u16);
1517        self.as_vec_mut().extend(value.to_ne_bytes());
1518        self
1519    }
1520    #[doc = "ifindex of the main netdevice linked to the PSP device, or the ifindex\nto associate with the PSP device.\n"]
1521    pub fn push_ifindex(mut self, value: u32) -> Self {
1522        push_header(self.as_vec_mut(), 2u16, 4 as u16);
1523        self.as_vec_mut().extend(value.to_ne_bytes());
1524        self
1525    }
1526    #[doc = "Bitmask of PSP versions supported by the device.\n\nAssociated type: [`Version`] (1 bit per enumeration)"]
1527    pub fn push_psp_versions_cap(mut self, value: u32) -> Self {
1528        push_header(self.as_vec_mut(), 3u16, 4 as u16);
1529        self.as_vec_mut().extend(value.to_ne_bytes());
1530        self
1531    }
1532    #[doc = "Bitmask of currently enabled (accepted on Rx) PSP versions.\n\nAssociated type: [`Version`] (1 bit per enumeration)"]
1533    pub fn push_psp_versions_ena(mut self, value: u32) -> Self {
1534        push_header(self.as_vec_mut(), 4u16, 4 as u16);
1535        self.as_vec_mut().extend(value.to_ne_bytes());
1536        self
1537    }
1538    #[doc = "List of associated virtual devices.\n\nAttribute may repeat multiple times (treat it as array)"]
1539    pub fn nested_assoc_list(mut self) -> PushAssocDevInfo<Self> {
1540        let header_offset = push_nested_header(self.as_vec_mut(), 5u16);
1541        PushAssocDevInfo {
1542            prev: Some(self),
1543            header_offset: Some(header_offset),
1544        }
1545    }
1546    #[doc = "Network namespace ID for the device to associate/disassociate. Optional\nfor dev-assoc and dev-disassoc; if not present, the device is looked up\nin the caller\\'s network namespace.\n"]
1547    pub fn push_nsid(mut self, value: i32) -> Self {
1548        push_header(self.as_vec_mut(), 6u16, 4 as u16);
1549        self.as_vec_mut().extend(value.to_ne_bytes());
1550        self
1551    }
1552    #[doc = "Flag indicating the PSP device is an associated device from a different\nnetwork namespace. Present when in associated namespace, absent when in\nprimary/host namespace.\n"]
1553    pub fn push_by_association(mut self, value: ()) -> Self {
1554        push_header(self.as_vec_mut(), 7u16, 0 as u16);
1555        self
1556    }
1557}
1558impl<Prev: Pusher> Drop for PushDev<Prev> {
1559    fn drop(&mut self) {
1560        if let Some(prev) = &mut self.prev {
1561            if let Some(header_offset) = &self.header_offset {
1562                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1563            }
1564        }
1565    }
1566}
1567pub struct PushAssoc<Prev: Pusher> {
1568    pub(crate) prev: Option<Prev>,
1569    pub(crate) header_offset: Option<usize>,
1570}
1571impl<Prev: Pusher> Pusher for PushAssoc<Prev> {
1572    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1573        self.prev.as_mut().unwrap().as_vec_mut()
1574    }
1575    fn as_vec(&self) -> &Vec<u8> {
1576        self.prev.as_ref().unwrap().as_vec()
1577    }
1578}
1579impl<Prev: Pusher> PushAssoc<Prev> {
1580    pub fn new(prev: Prev) -> Self {
1581        Self {
1582            prev: Some(prev),
1583            header_offset: None,
1584        }
1585    }
1586    pub fn end_nested(mut self) -> Prev {
1587        let mut prev = self.prev.take().unwrap();
1588        if let Some(header_offset) = &self.header_offset {
1589            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1590        }
1591        prev
1592    }
1593    #[doc = "PSP device ID.\n"]
1594    pub fn push_dev_id(mut self, value: u32) -> Self {
1595        push_header(self.as_vec_mut(), 1u16, 4 as u16);
1596        self.as_vec_mut().extend(value.to_ne_bytes());
1597        self
1598    }
1599    #[doc = "PSP versions (AEAD and protocol version) used by this association,\ndictates the size of the key.\n\nAssociated type: [`Version`] (enum)"]
1600    pub fn push_version(mut self, value: u32) -> Self {
1601        push_header(self.as_vec_mut(), 2u16, 4 as u16);
1602        self.as_vec_mut().extend(value.to_ne_bytes());
1603        self
1604    }
1605    pub fn nested_rx_key(mut self) -> PushKeys<Self> {
1606        let header_offset = push_nested_header(self.as_vec_mut(), 3u16);
1607        PushKeys {
1608            prev: Some(self),
1609            header_offset: Some(header_offset),
1610        }
1611    }
1612    pub fn nested_tx_key(mut self) -> PushKeys<Self> {
1613        let header_offset = push_nested_header(self.as_vec_mut(), 4u16);
1614        PushKeys {
1615            prev: Some(self),
1616            header_offset: Some(header_offset),
1617        }
1618    }
1619    #[doc = "Sockets which should be bound to the association immediately.\n"]
1620    pub fn push_sock_fd(mut self, value: u32) -> Self {
1621        push_header(self.as_vec_mut(), 5u16, 4 as u16);
1622        self.as_vec_mut().extend(value.to_ne_bytes());
1623        self
1624    }
1625}
1626impl<Prev: Pusher> Drop for PushAssoc<Prev> {
1627    fn drop(&mut self) {
1628        if let Some(prev) = &mut self.prev {
1629            if let Some(header_offset) = &self.header_offset {
1630                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1631            }
1632        }
1633    }
1634}
1635pub struct PushKeys<Prev: Pusher> {
1636    pub(crate) prev: Option<Prev>,
1637    pub(crate) header_offset: Option<usize>,
1638}
1639impl<Prev: Pusher> Pusher for PushKeys<Prev> {
1640    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1641        self.prev.as_mut().unwrap().as_vec_mut()
1642    }
1643    fn as_vec(&self) -> &Vec<u8> {
1644        self.prev.as_ref().unwrap().as_vec()
1645    }
1646}
1647impl<Prev: Pusher> PushKeys<Prev> {
1648    pub fn new(prev: Prev) -> Self {
1649        Self {
1650            prev: Some(prev),
1651            header_offset: None,
1652        }
1653    }
1654    pub fn end_nested(mut self) -> Prev {
1655        let mut prev = self.prev.take().unwrap();
1656        if let Some(header_offset) = &self.header_offset {
1657            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1658        }
1659        prev
1660    }
1661    pub fn push_key(mut self, value: &[u8]) -> Self {
1662        push_header(self.as_vec_mut(), 1u16, value.len() as u16);
1663        self.as_vec_mut().extend(value);
1664        self
1665    }
1666    #[doc = "Security Parameters Index (SPI) of the association.\n"]
1667    pub fn push_spi(mut self, value: u32) -> Self {
1668        push_header(self.as_vec_mut(), 2u16, 4 as u16);
1669        self.as_vec_mut().extend(value.to_ne_bytes());
1670        self
1671    }
1672}
1673impl<Prev: Pusher> Drop for PushKeys<Prev> {
1674    fn drop(&mut self) {
1675        if let Some(prev) = &mut self.prev {
1676            if let Some(header_offset) = &self.header_offset {
1677                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1678            }
1679        }
1680    }
1681}
1682pub struct PushStats<Prev: Pusher> {
1683    pub(crate) prev: Option<Prev>,
1684    pub(crate) header_offset: Option<usize>,
1685}
1686impl<Prev: Pusher> Pusher for PushStats<Prev> {
1687    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1688        self.prev.as_mut().unwrap().as_vec_mut()
1689    }
1690    fn as_vec(&self) -> &Vec<u8> {
1691        self.prev.as_ref().unwrap().as_vec()
1692    }
1693}
1694impl<Prev: Pusher> PushStats<Prev> {
1695    pub fn new(prev: Prev) -> Self {
1696        Self {
1697            prev: Some(prev),
1698            header_offset: None,
1699        }
1700    }
1701    pub fn end_nested(mut self) -> Prev {
1702        let mut prev = self.prev.take().unwrap();
1703        if let Some(header_offset) = &self.header_offset {
1704            finalize_nested_header(prev.as_vec_mut(), *header_offset);
1705        }
1706        prev
1707    }
1708    #[doc = "PSP device ID.\n"]
1709    pub fn push_dev_id(mut self, value: u32) -> Self {
1710        push_header(self.as_vec_mut(), 1u16, 4 as u16);
1711        self.as_vec_mut().extend(value.to_ne_bytes());
1712        self
1713    }
1714    #[doc = "Number of key rotations during the lifetime of the device. Kernel\nstatistic.\n"]
1715    pub fn push_key_rotations(mut self, value: u32) -> Self {
1716        push_header(self.as_vec_mut(), 2u16, 4 as u16);
1717        self.as_vec_mut().extend(value.to_ne_bytes());
1718        self
1719    }
1720    #[doc = "Number of times a socket\\'s Rx got shut down due to using a key which\nwent stale (fully rotated out). Kernel statistic.\n"]
1721    pub fn push_stale_events(mut self, value: u32) -> Self {
1722        push_header(self.as_vec_mut(), 3u16, 4 as u16);
1723        self.as_vec_mut().extend(value.to_ne_bytes());
1724        self
1725    }
1726    #[doc = "Number of successfully processed and authenticated PSP packets. Device\nstatistic (from the PSP spec).\n"]
1727    pub fn push_rx_packets(mut self, value: u32) -> Self {
1728        push_header(self.as_vec_mut(), 4u16, 4 as u16);
1729        self.as_vec_mut().extend(value.to_ne_bytes());
1730        self
1731    }
1732    #[doc = "Number of successfully authenticated PSP bytes received, counting from\nthe first byte after the IV through the last byte of payload. The fixed\ninitial portion of the PSP header (16 bytes) and the PSP trailer/ICV (16\nbytes) are not included in this count. Device statistic (from the PSP\nspec).\n"]
1733    pub fn push_rx_bytes(mut self, value: u32) -> Self {
1734        push_header(self.as_vec_mut(), 5u16, 4 as u16);
1735        self.as_vec_mut().extend(value.to_ne_bytes());
1736        self
1737    }
1738    #[doc = "Number of received PSP packets with unsuccessful authentication. Device\nstatistic (from the PSP spec).\n"]
1739    pub fn push_rx_auth_fail(mut self, value: u32) -> Self {
1740        push_header(self.as_vec_mut(), 6u16, 4 as u16);
1741        self.as_vec_mut().extend(value.to_ne_bytes());
1742        self
1743    }
1744    #[doc = "Number of received PSP packets with length/framing errors. Device\nstatistic (from the PSP spec).\n"]
1745    pub fn push_rx_error(mut self, value: u32) -> Self {
1746        push_header(self.as_vec_mut(), 7u16, 4 as u16);
1747        self.as_vec_mut().extend(value.to_ne_bytes());
1748        self
1749    }
1750    #[doc = "Number of received PSP packets with miscellaneous errors (invalid master\nkey indicated by SPI, unsupported version, etc.) Device statistic (from\nthe PSP spec).\n"]
1751    pub fn push_rx_bad(mut self, value: u32) -> Self {
1752        push_header(self.as_vec_mut(), 8u16, 4 as u16);
1753        self.as_vec_mut().extend(value.to_ne_bytes());
1754        self
1755    }
1756    #[doc = "Number of successfully processed PSP packets for transmission. Device\nstatistic (from the PSP spec).\n"]
1757    pub fn push_tx_packets(mut self, value: u32) -> Self {
1758        push_header(self.as_vec_mut(), 9u16, 4 as u16);
1759        self.as_vec_mut().extend(value.to_ne_bytes());
1760        self
1761    }
1762    #[doc = "Number of successfully processed PSP bytes for transmit, counting from\nthe first byte after the IV through the last byte of payload. The fixed\ninitial portion of the PSP header (16 bytes) and the PSP trailer/ICV (16\nbytes) are not included in this count. Device statistic (from the PSP\nspec).\n"]
1763    pub fn push_tx_bytes(mut self, value: u32) -> Self {
1764        push_header(self.as_vec_mut(), 10u16, 4 as u16);
1765        self.as_vec_mut().extend(value.to_ne_bytes());
1766        self
1767    }
1768    #[doc = "Number of PSP packets for transmission with errors. Device statistic\n(from the PSP spec).\n"]
1769    pub fn push_tx_error(mut self, value: u32) -> Self {
1770        push_header(self.as_vec_mut(), 11u16, 4 as u16);
1771        self.as_vec_mut().extend(value.to_ne_bytes());
1772        self
1773    }
1774}
1775impl<Prev: Pusher> Drop for PushStats<Prev> {
1776    fn drop(&mut self) {
1777        if let Some(prev) = &mut self.prev {
1778            if let Some(header_offset) = &self.header_offset {
1779                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1780            }
1781        }
1782    }
1783}
1784#[doc = "Notify attributes:\n- [`.get_id()`](IterableDev::get_id)\n- [`.get_ifindex()`](IterableDev::get_ifindex)\n- [`.get_psp_versions_cap()`](IterableDev::get_psp_versions_cap)\n- [`.get_psp_versions_ena()`](IterableDev::get_psp_versions_ena)\n- [`.get_assoc_list()`](IterableDev::get_assoc_list)\n- [`.get_by_association()`](IterableDev::get_by_association)\n"]
1785#[derive(Debug)]
1786pub struct OpDevAddNotif;
1787impl OpDevAddNotif {
1788    pub const CMD: u8 = 2u8;
1789    pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableDev<'a> {
1790        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1791        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
1792    }
1793}
1794#[doc = "Notify attributes:\n- [`.get_id()`](IterableDev::get_id)\n- [`.get_ifindex()`](IterableDev::get_ifindex)\n- [`.get_psp_versions_cap()`](IterableDev::get_psp_versions_cap)\n- [`.get_psp_versions_ena()`](IterableDev::get_psp_versions_ena)\n- [`.get_assoc_list()`](IterableDev::get_assoc_list)\n- [`.get_by_association()`](IterableDev::get_by_association)\n"]
1795#[derive(Debug)]
1796pub struct OpDevDelNotif;
1797impl OpDevDelNotif {
1798    pub const CMD: u8 = 3u8;
1799    pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableDev<'a> {
1800        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1801        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
1802    }
1803}
1804#[doc = "Notify attributes:\n- [`.get_id()`](IterableDev::get_id)\n- [`.get_ifindex()`](IterableDev::get_ifindex)\n- [`.get_psp_versions_cap()`](IterableDev::get_psp_versions_cap)\n- [`.get_psp_versions_ena()`](IterableDev::get_psp_versions_ena)\n- [`.get_assoc_list()`](IterableDev::get_assoc_list)\n- [`.get_by_association()`](IterableDev::get_by_association)\n"]
1805#[derive(Debug)]
1806pub struct OpDevChangeNotif;
1807impl OpDevChangeNotif {
1808    pub const CMD: u8 = 5u8;
1809    pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableDev<'a> {
1810        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1811        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
1812    }
1813}
1814#[doc = "Notify attributes:\n- [`.get_id()`](IterableDev::get_id)\n"]
1815#[derive(Debug)]
1816pub struct OpKeyRotateNotif;
1817impl OpKeyRotateNotif {
1818    pub const CMD: u8 = 7u8;
1819    pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableDev<'a> {
1820        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1821        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
1822    }
1823}
1824pub struct NotifGroup;
1825impl NotifGroup {
1826    #[doc = "Notifications:\n- [`OpDevAddNotif`]\n- [`OpDevDelNotif`]\n- [`OpDevChangeNotif`]\n"]
1827    pub const MGMT: &str = "mgmt";
1828    #[doc = "Notifications:\n- [`OpDevAddNotif`]\n- [`OpDevDelNotif`]\n- [`OpDevChangeNotif`]\n"]
1829    pub const MGMT_CSTR: &CStr = c"mgmt";
1830    #[doc = "Notifications:\n- [`OpKeyRotateNotif`]\n"]
1831    pub const USE: &str = "use";
1832    #[doc = "Notifications:\n- [`OpKeyRotateNotif`]\n"]
1833    pub const USE_CSTR: &CStr = c"use";
1834}
1835#[doc = "Get / dump information about PSP capable devices on the system.\n\nReply attributes:\n- [.get_id()](IterableDev::get_id)\n- [.get_ifindex()](IterableDev::get_ifindex)\n- [.get_psp_versions_cap()](IterableDev::get_psp_versions_cap)\n- [.get_psp_versions_ena()](IterableDev::get_psp_versions_ena)\n- [.get_assoc_list()](IterableDev::get_assoc_list)\n- [.get_by_association()](IterableDev::get_by_association)\n\n"]
1836#[derive(Debug)]
1837pub struct OpDevGetDump<'r> {
1838    request: Request<'r>,
1839}
1840impl<'r> OpDevGetDump<'r> {
1841    pub fn new(mut request: Request<'r>) -> Self {
1842        Self::write_header(request.buf_mut());
1843        Self {
1844            request: request.set_dump(),
1845        }
1846    }
1847    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDev<&'buf mut Vec<u8>> {
1848        Self::write_header(buf);
1849        PushDev::new(buf)
1850    }
1851    pub fn encode(&mut self) -> PushDev<&mut Vec<u8>> {
1852        PushDev::new(self.request.buf_mut())
1853    }
1854    pub fn into_encoder(self) -> PushDev<RequestBuf<'r>> {
1855        PushDev::new(self.request.buf)
1856    }
1857    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDev<'a> {
1858        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1859        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
1860    }
1861    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1862        let mut header = BuiltinNfgenmsg::new();
1863        header.cmd = 1u8;
1864        header.version = 1u8;
1865        prev.as_vec_mut().extend(header.as_slice());
1866    }
1867}
1868impl NetlinkRequest for OpDevGetDump<'_> {
1869    fn protocol(&self) -> Protocol {
1870        Protocol::Generic("psp".as_bytes())
1871    }
1872    fn flags(&self) -> u16 {
1873        self.request.flags
1874    }
1875    fn payload(&self) -> &[u8] {
1876        self.request.buf()
1877    }
1878    type ReplyType<'buf> = IterableDev<'buf>;
1879    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1880        Self::decode_request(buf)
1881    }
1882    fn lookup(
1883        buf: &[u8],
1884        offset: usize,
1885        missing_type: Option<u16>,
1886    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1887        Self::decode_request(buf).lookup_attr(offset, missing_type)
1888    }
1889}
1890#[doc = "Get / dump information about PSP capable devices on the system.\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n\nReply attributes:\n- [.get_id()](IterableDev::get_id)\n- [.get_ifindex()](IterableDev::get_ifindex)\n- [.get_psp_versions_cap()](IterableDev::get_psp_versions_cap)\n- [.get_psp_versions_ena()](IterableDev::get_psp_versions_ena)\n- [.get_assoc_list()](IterableDev::get_assoc_list)\n- [.get_by_association()](IterableDev::get_by_association)\n\n"]
1891#[derive(Debug)]
1892pub struct OpDevGetDo<'r> {
1893    request: Request<'r>,
1894}
1895impl<'r> OpDevGetDo<'r> {
1896    pub fn new(mut request: Request<'r>) -> Self {
1897        Self::write_header(request.buf_mut());
1898        Self { request: request }
1899    }
1900    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDev<&'buf mut Vec<u8>> {
1901        Self::write_header(buf);
1902        PushDev::new(buf)
1903    }
1904    pub fn encode(&mut self) -> PushDev<&mut Vec<u8>> {
1905        PushDev::new(self.request.buf_mut())
1906    }
1907    pub fn into_encoder(self) -> PushDev<RequestBuf<'r>> {
1908        PushDev::new(self.request.buf)
1909    }
1910    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDev<'a> {
1911        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1912        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
1913    }
1914    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1915        let mut header = BuiltinNfgenmsg::new();
1916        header.cmd = 1u8;
1917        header.version = 1u8;
1918        prev.as_vec_mut().extend(header.as_slice());
1919    }
1920}
1921impl NetlinkRequest for OpDevGetDo<'_> {
1922    fn protocol(&self) -> Protocol {
1923        Protocol::Generic("psp".as_bytes())
1924    }
1925    fn flags(&self) -> u16 {
1926        self.request.flags
1927    }
1928    fn payload(&self) -> &[u8] {
1929        self.request.buf()
1930    }
1931    type ReplyType<'buf> = IterableDev<'buf>;
1932    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1933        Self::decode_request(buf)
1934    }
1935    fn lookup(
1936        buf: &[u8],
1937        offset: usize,
1938        missing_type: Option<u16>,
1939    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1940        Self::decode_request(buf).lookup_attr(offset, missing_type)
1941    }
1942}
1943#[doc = "Set the configuration of a PSP device.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n- [.push_psp_versions_ena()](PushDev::push_psp_versions_ena)\n\n"]
1944#[derive(Debug)]
1945pub struct OpDevSetDo<'r> {
1946    request: Request<'r>,
1947}
1948impl<'r> OpDevSetDo<'r> {
1949    pub fn new(mut request: Request<'r>) -> Self {
1950        Self::write_header(request.buf_mut());
1951        Self { request: request }
1952    }
1953    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDev<&'buf mut Vec<u8>> {
1954        Self::write_header(buf);
1955        PushDev::new(buf)
1956    }
1957    pub fn encode(&mut self) -> PushDev<&mut Vec<u8>> {
1958        PushDev::new(self.request.buf_mut())
1959    }
1960    pub fn into_encoder(self) -> PushDev<RequestBuf<'r>> {
1961        PushDev::new(self.request.buf)
1962    }
1963    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDev<'a> {
1964        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1965        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
1966    }
1967    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1968        let mut header = BuiltinNfgenmsg::new();
1969        header.cmd = 4u8;
1970        header.version = 1u8;
1971        prev.as_vec_mut().extend(header.as_slice());
1972    }
1973}
1974impl NetlinkRequest for OpDevSetDo<'_> {
1975    fn protocol(&self) -> Protocol {
1976        Protocol::Generic("psp".as_bytes())
1977    }
1978    fn flags(&self) -> u16 {
1979        self.request.flags
1980    }
1981    fn payload(&self) -> &[u8] {
1982        self.request.buf()
1983    }
1984    type ReplyType<'buf> = IterableDev<'buf>;
1985    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1986        Self::decode_request(buf)
1987    }
1988    fn lookup(
1989        buf: &[u8],
1990        offset: usize,
1991        missing_type: Option<u16>,
1992    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1993        Self::decode_request(buf).lookup_attr(offset, missing_type)
1994    }
1995}
1996#[doc = "Rotate the device key.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n\nReply attributes:\n- [.get_id()](IterableDev::get_id)\n\n"]
1997#[derive(Debug)]
1998pub struct OpKeyRotateDo<'r> {
1999    request: Request<'r>,
2000}
2001impl<'r> OpKeyRotateDo<'r> {
2002    pub fn new(mut request: Request<'r>) -> Self {
2003        Self::write_header(request.buf_mut());
2004        Self { request: request }
2005    }
2006    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDev<&'buf mut Vec<u8>> {
2007        Self::write_header(buf);
2008        PushDev::new(buf)
2009    }
2010    pub fn encode(&mut self) -> PushDev<&mut Vec<u8>> {
2011        PushDev::new(self.request.buf_mut())
2012    }
2013    pub fn into_encoder(self) -> PushDev<RequestBuf<'r>> {
2014        PushDev::new(self.request.buf)
2015    }
2016    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDev<'a> {
2017        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
2018        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
2019    }
2020    fn write_header<Prev: Pusher>(prev: &mut Prev) {
2021        let mut header = BuiltinNfgenmsg::new();
2022        header.cmd = 6u8;
2023        header.version = 1u8;
2024        prev.as_vec_mut().extend(header.as_slice());
2025    }
2026}
2027impl NetlinkRequest for OpKeyRotateDo<'_> {
2028    fn protocol(&self) -> Protocol {
2029        Protocol::Generic("psp".as_bytes())
2030    }
2031    fn flags(&self) -> u16 {
2032        self.request.flags
2033    }
2034    fn payload(&self) -> &[u8] {
2035        self.request.buf()
2036    }
2037    type ReplyType<'buf> = IterableDev<'buf>;
2038    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2039        Self::decode_request(buf)
2040    }
2041    fn lookup(
2042        buf: &[u8],
2043        offset: usize,
2044        missing_type: Option<u16>,
2045    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2046        Self::decode_request(buf).lookup_attr(offset, missing_type)
2047    }
2048}
2049#[doc = "Allocate a new Rx key + SPI pair, associate it with a socket.\n\nRequest attributes:\n- [.push_dev_id()](PushAssoc::push_dev_id)\n- [.push_version()](PushAssoc::push_version)\n- [.push_sock_fd()](PushAssoc::push_sock_fd)\n\nReply attributes:\n- [.get_dev_id()](IterableAssoc::get_dev_id)\n- [.get_rx_key()](IterableAssoc::get_rx_key)\n\n"]
2050#[derive(Debug)]
2051pub struct OpRxAssocDo<'r> {
2052    request: Request<'r>,
2053}
2054impl<'r> OpRxAssocDo<'r> {
2055    pub fn new(mut request: Request<'r>) -> Self {
2056        Self::write_header(request.buf_mut());
2057        Self { request: request }
2058    }
2059    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushAssoc<&'buf mut Vec<u8>> {
2060        Self::write_header(buf);
2061        PushAssoc::new(buf)
2062    }
2063    pub fn encode(&mut self) -> PushAssoc<&mut Vec<u8>> {
2064        PushAssoc::new(self.request.buf_mut())
2065    }
2066    pub fn into_encoder(self) -> PushAssoc<RequestBuf<'r>> {
2067        PushAssoc::new(self.request.buf)
2068    }
2069    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableAssoc<'a> {
2070        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
2071        IterableAssoc::with_loc(attrs, buf.as_ptr() as usize)
2072    }
2073    fn write_header<Prev: Pusher>(prev: &mut Prev) {
2074        let mut header = BuiltinNfgenmsg::new();
2075        header.cmd = 8u8;
2076        header.version = 1u8;
2077        prev.as_vec_mut().extend(header.as_slice());
2078    }
2079}
2080impl NetlinkRequest for OpRxAssocDo<'_> {
2081    fn protocol(&self) -> Protocol {
2082        Protocol::Generic("psp".as_bytes())
2083    }
2084    fn flags(&self) -> u16 {
2085        self.request.flags
2086    }
2087    fn payload(&self) -> &[u8] {
2088        self.request.buf()
2089    }
2090    type ReplyType<'buf> = IterableAssoc<'buf>;
2091    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2092        Self::decode_request(buf)
2093    }
2094    fn lookup(
2095        buf: &[u8],
2096        offset: usize,
2097        missing_type: Option<u16>,
2098    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2099        Self::decode_request(buf).lookup_attr(offset, missing_type)
2100    }
2101}
2102#[doc = "Add a PSP Tx association.\n\nRequest attributes:\n- [.push_dev_id()](PushAssoc::push_dev_id)\n- [.push_version()](PushAssoc::push_version)\n- [.nested_tx_key()](PushAssoc::nested_tx_key)\n- [.push_sock_fd()](PushAssoc::push_sock_fd)\n\n"]
2103#[derive(Debug)]
2104pub struct OpTxAssocDo<'r> {
2105    request: Request<'r>,
2106}
2107impl<'r> OpTxAssocDo<'r> {
2108    pub fn new(mut request: Request<'r>) -> Self {
2109        Self::write_header(request.buf_mut());
2110        Self { request: request }
2111    }
2112    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushAssoc<&'buf mut Vec<u8>> {
2113        Self::write_header(buf);
2114        PushAssoc::new(buf)
2115    }
2116    pub fn encode(&mut self) -> PushAssoc<&mut Vec<u8>> {
2117        PushAssoc::new(self.request.buf_mut())
2118    }
2119    pub fn into_encoder(self) -> PushAssoc<RequestBuf<'r>> {
2120        PushAssoc::new(self.request.buf)
2121    }
2122    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableAssoc<'a> {
2123        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
2124        IterableAssoc::with_loc(attrs, buf.as_ptr() as usize)
2125    }
2126    fn write_header<Prev: Pusher>(prev: &mut Prev) {
2127        let mut header = BuiltinNfgenmsg::new();
2128        header.cmd = 9u8;
2129        header.version = 1u8;
2130        prev.as_vec_mut().extend(header.as_slice());
2131    }
2132}
2133impl NetlinkRequest for OpTxAssocDo<'_> {
2134    fn protocol(&self) -> Protocol {
2135        Protocol::Generic("psp".as_bytes())
2136    }
2137    fn flags(&self) -> u16 {
2138        self.request.flags
2139    }
2140    fn payload(&self) -> &[u8] {
2141        self.request.buf()
2142    }
2143    type ReplyType<'buf> = IterableAssoc<'buf>;
2144    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2145        Self::decode_request(buf)
2146    }
2147    fn lookup(
2148        buf: &[u8],
2149        offset: usize,
2150        missing_type: Option<u16>,
2151    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2152        Self::decode_request(buf).lookup_attr(offset, missing_type)
2153    }
2154}
2155#[doc = "Get device statistics.\n\nReply attributes:\n- [.get_dev_id()](IterableStats::get_dev_id)\n- [.get_key_rotations()](IterableStats::get_key_rotations)\n- [.get_stale_events()](IterableStats::get_stale_events)\n- [.get_rx_packets()](IterableStats::get_rx_packets)\n- [.get_rx_bytes()](IterableStats::get_rx_bytes)\n- [.get_rx_auth_fail()](IterableStats::get_rx_auth_fail)\n- [.get_rx_error()](IterableStats::get_rx_error)\n- [.get_rx_bad()](IterableStats::get_rx_bad)\n- [.get_tx_packets()](IterableStats::get_tx_packets)\n- [.get_tx_bytes()](IterableStats::get_tx_bytes)\n- [.get_tx_error()](IterableStats::get_tx_error)\n\n"]
2156#[derive(Debug)]
2157pub struct OpGetStatsDump<'r> {
2158    request: Request<'r>,
2159}
2160impl<'r> OpGetStatsDump<'r> {
2161    pub fn new(mut request: Request<'r>) -> Self {
2162        Self::write_header(request.buf_mut());
2163        Self {
2164            request: request.set_dump(),
2165        }
2166    }
2167    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushStats<&'buf mut Vec<u8>> {
2168        Self::write_header(buf);
2169        PushStats::new(buf)
2170    }
2171    pub fn encode(&mut self) -> PushStats<&mut Vec<u8>> {
2172        PushStats::new(self.request.buf_mut())
2173    }
2174    pub fn into_encoder(self) -> PushStats<RequestBuf<'r>> {
2175        PushStats::new(self.request.buf)
2176    }
2177    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableStats<'a> {
2178        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
2179        IterableStats::with_loc(attrs, buf.as_ptr() as usize)
2180    }
2181    fn write_header<Prev: Pusher>(prev: &mut Prev) {
2182        let mut header = BuiltinNfgenmsg::new();
2183        header.cmd = 10u8;
2184        header.version = 1u8;
2185        prev.as_vec_mut().extend(header.as_slice());
2186    }
2187}
2188impl NetlinkRequest for OpGetStatsDump<'_> {
2189    fn protocol(&self) -> Protocol {
2190        Protocol::Generic("psp".as_bytes())
2191    }
2192    fn flags(&self) -> u16 {
2193        self.request.flags
2194    }
2195    fn payload(&self) -> &[u8] {
2196        self.request.buf()
2197    }
2198    type ReplyType<'buf> = IterableStats<'buf>;
2199    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2200        Self::decode_request(buf)
2201    }
2202    fn lookup(
2203        buf: &[u8],
2204        offset: usize,
2205        missing_type: Option<u16>,
2206    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2207        Self::decode_request(buf).lookup_attr(offset, missing_type)
2208    }
2209}
2210#[doc = "Get device statistics.\n\nRequest attributes:\n- [.push_dev_id()](PushStats::push_dev_id)\n\nReply attributes:\n- [.get_dev_id()](IterableStats::get_dev_id)\n- [.get_key_rotations()](IterableStats::get_key_rotations)\n- [.get_stale_events()](IterableStats::get_stale_events)\n- [.get_rx_packets()](IterableStats::get_rx_packets)\n- [.get_rx_bytes()](IterableStats::get_rx_bytes)\n- [.get_rx_auth_fail()](IterableStats::get_rx_auth_fail)\n- [.get_rx_error()](IterableStats::get_rx_error)\n- [.get_rx_bad()](IterableStats::get_rx_bad)\n- [.get_tx_packets()](IterableStats::get_tx_packets)\n- [.get_tx_bytes()](IterableStats::get_tx_bytes)\n- [.get_tx_error()](IterableStats::get_tx_error)\n\n"]
2211#[derive(Debug)]
2212pub struct OpGetStatsDo<'r> {
2213    request: Request<'r>,
2214}
2215impl<'r> OpGetStatsDo<'r> {
2216    pub fn new(mut request: Request<'r>) -> Self {
2217        Self::write_header(request.buf_mut());
2218        Self { request: request }
2219    }
2220    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushStats<&'buf mut Vec<u8>> {
2221        Self::write_header(buf);
2222        PushStats::new(buf)
2223    }
2224    pub fn encode(&mut self) -> PushStats<&mut Vec<u8>> {
2225        PushStats::new(self.request.buf_mut())
2226    }
2227    pub fn into_encoder(self) -> PushStats<RequestBuf<'r>> {
2228        PushStats::new(self.request.buf)
2229    }
2230    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableStats<'a> {
2231        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
2232        IterableStats::with_loc(attrs, buf.as_ptr() as usize)
2233    }
2234    fn write_header<Prev: Pusher>(prev: &mut Prev) {
2235        let mut header = BuiltinNfgenmsg::new();
2236        header.cmd = 10u8;
2237        header.version = 1u8;
2238        prev.as_vec_mut().extend(header.as_slice());
2239    }
2240}
2241impl NetlinkRequest for OpGetStatsDo<'_> {
2242    fn protocol(&self) -> Protocol {
2243        Protocol::Generic("psp".as_bytes())
2244    }
2245    fn flags(&self) -> u16 {
2246        self.request.flags
2247    }
2248    fn payload(&self) -> &[u8] {
2249        self.request.buf()
2250    }
2251    type ReplyType<'buf> = IterableStats<'buf>;
2252    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2253        Self::decode_request(buf)
2254    }
2255    fn lookup(
2256        buf: &[u8],
2257        offset: usize,
2258        missing_type: Option<u16>,
2259    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2260        Self::decode_request(buf).lookup_attr(offset, missing_type)
2261    }
2262}
2263#[doc = "Associate a network device with a PSP device.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n- [.push_ifindex()](PushDev::push_ifindex)\n- [.push_nsid()](PushDev::push_nsid)\n\n"]
2264#[derive(Debug)]
2265pub struct OpDevAssocDo<'r> {
2266    request: Request<'r>,
2267}
2268impl<'r> OpDevAssocDo<'r> {
2269    pub fn new(mut request: Request<'r>) -> Self {
2270        Self::write_header(request.buf_mut());
2271        Self { request: request }
2272    }
2273    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDev<&'buf mut Vec<u8>> {
2274        Self::write_header(buf);
2275        PushDev::new(buf)
2276    }
2277    pub fn encode(&mut self) -> PushDev<&mut Vec<u8>> {
2278        PushDev::new(self.request.buf_mut())
2279    }
2280    pub fn into_encoder(self) -> PushDev<RequestBuf<'r>> {
2281        PushDev::new(self.request.buf)
2282    }
2283    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDev<'a> {
2284        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
2285        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
2286    }
2287    fn write_header<Prev: Pusher>(prev: &mut Prev) {
2288        let mut header = BuiltinNfgenmsg::new();
2289        header.cmd = 11u8;
2290        header.version = 1u8;
2291        prev.as_vec_mut().extend(header.as_slice());
2292    }
2293}
2294impl NetlinkRequest for OpDevAssocDo<'_> {
2295    fn protocol(&self) -> Protocol {
2296        Protocol::Generic("psp".as_bytes())
2297    }
2298    fn flags(&self) -> u16 {
2299        self.request.flags
2300    }
2301    fn payload(&self) -> &[u8] {
2302        self.request.buf()
2303    }
2304    type ReplyType<'buf> = IterableDev<'buf>;
2305    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2306        Self::decode_request(buf)
2307    }
2308    fn lookup(
2309        buf: &[u8],
2310        offset: usize,
2311        missing_type: Option<u16>,
2312    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2313        Self::decode_request(buf).lookup_attr(offset, missing_type)
2314    }
2315}
2316#[doc = "Disassociate a network device from a PSP device.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n- [.push_ifindex()](PushDev::push_ifindex)\n- [.push_nsid()](PushDev::push_nsid)\n\n"]
2317#[derive(Debug)]
2318pub struct OpDevDisassocDo<'r> {
2319    request: Request<'r>,
2320}
2321impl<'r> OpDevDisassocDo<'r> {
2322    pub fn new(mut request: Request<'r>) -> Self {
2323        Self::write_header(request.buf_mut());
2324        Self { request: request }
2325    }
2326    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushDev<&'buf mut Vec<u8>> {
2327        Self::write_header(buf);
2328        PushDev::new(buf)
2329    }
2330    pub fn encode(&mut self) -> PushDev<&mut Vec<u8>> {
2331        PushDev::new(self.request.buf_mut())
2332    }
2333    pub fn into_encoder(self) -> PushDev<RequestBuf<'r>> {
2334        PushDev::new(self.request.buf)
2335    }
2336    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableDev<'a> {
2337        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
2338        IterableDev::with_loc(attrs, buf.as_ptr() as usize)
2339    }
2340    fn write_header<Prev: Pusher>(prev: &mut Prev) {
2341        let mut header = BuiltinNfgenmsg::new();
2342        header.cmd = 12u8;
2343        header.version = 1u8;
2344        prev.as_vec_mut().extend(header.as_slice());
2345    }
2346}
2347impl NetlinkRequest for OpDevDisassocDo<'_> {
2348    fn protocol(&self) -> Protocol {
2349        Protocol::Generic("psp".as_bytes())
2350    }
2351    fn flags(&self) -> u16 {
2352        self.request.flags
2353    }
2354    fn payload(&self) -> &[u8] {
2355        self.request.buf()
2356    }
2357    type ReplyType<'buf> = IterableDev<'buf>;
2358    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2359        Self::decode_request(buf)
2360    }
2361    fn lookup(
2362        buf: &[u8],
2363        offset: usize,
2364        missing_type: Option<u16>,
2365    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2366        Self::decode_request(buf).lookup_attr(offset, missing_type)
2367    }
2368}
2369use crate::traits::LookupFn;
2370use crate::utils::RequestBuf;
2371#[derive(Debug)]
2372pub struct Request<'buf> {
2373    buf: RequestBuf<'buf>,
2374    flags: u16,
2375    writeback: Option<&'buf mut Option<RequestInfo>>,
2376}
2377#[allow(unused)]
2378#[derive(Debug, Clone)]
2379pub struct RequestInfo {
2380    protocol: Protocol,
2381    flags: u16,
2382    name: &'static str,
2383    lookup: LookupFn,
2384}
2385impl Request<'static> {
2386    pub fn new() -> Self {
2387        Self::new_from_buf(Vec::new())
2388    }
2389    pub fn new_from_buf(buf: Vec<u8>) -> Self {
2390        Self {
2391            flags: 0,
2392            buf: RequestBuf::Own(buf),
2393            writeback: None,
2394        }
2395    }
2396    pub fn into_buf(self) -> Vec<u8> {
2397        match self.buf {
2398            RequestBuf::Own(buf) => buf,
2399            _ => unreachable!(),
2400        }
2401    }
2402}
2403impl<'buf> Request<'buf> {
2404    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
2405        buf.clear();
2406        Self::new_extend(buf)
2407    }
2408    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
2409        Self {
2410            flags: 0,
2411            buf: RequestBuf::Ref(buf),
2412            writeback: None,
2413        }
2414    }
2415    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
2416        let Some(writeback) = &mut self.writeback else {
2417            return;
2418        };
2419        **writeback = Some(RequestInfo {
2420            protocol,
2421            flags: self.flags,
2422            name,
2423            lookup,
2424        })
2425    }
2426    pub fn buf(&self) -> &Vec<u8> {
2427        self.buf.buf()
2428    }
2429    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2430        self.buf.buf_mut()
2431    }
2432    #[doc = "Set `NLM_F_CREATE` flag"]
2433    pub fn set_create(mut self) -> Self {
2434        self.flags |= consts::NLM_F_CREATE as u16;
2435        self
2436    }
2437    #[doc = "Set `NLM_F_EXCL` flag"]
2438    pub fn set_excl(mut self) -> Self {
2439        self.flags |= consts::NLM_F_EXCL as u16;
2440        self
2441    }
2442    #[doc = "Set `NLM_F_REPLACE` flag"]
2443    pub fn set_replace(mut self) -> Self {
2444        self.flags |= consts::NLM_F_REPLACE as u16;
2445        self
2446    }
2447    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
2448    pub fn set_change(self) -> Self {
2449        self.set_create().set_replace()
2450    }
2451    #[doc = "Set `NLM_F_APPEND` flag"]
2452    pub fn set_append(mut self) -> Self {
2453        self.flags |= consts::NLM_F_APPEND as u16;
2454        self
2455    }
2456    #[doc = "Set `self.flags |= flags`"]
2457    pub fn set_flags(mut self, flags: u16) -> Self {
2458        self.flags |= flags;
2459        self
2460    }
2461    #[doc = "Set `self.flags ^= self.flags & flags`"]
2462    pub fn unset_flags(mut self, flags: u16) -> Self {
2463        self.flags ^= self.flags & flags;
2464        self
2465    }
2466    #[doc = "Set `NLM_F_DUMP` flag"]
2467    fn set_dump(mut self) -> Self {
2468        self.flags |= consts::NLM_F_DUMP as u16;
2469        self
2470    }
2471    #[doc = "Get / dump information about PSP capable devices on the system.\n\nReply attributes:\n- [.get_id()](IterableDev::get_id)\n- [.get_ifindex()](IterableDev::get_ifindex)\n- [.get_psp_versions_cap()](IterableDev::get_psp_versions_cap)\n- [.get_psp_versions_ena()](IterableDev::get_psp_versions_ena)\n- [.get_assoc_list()](IterableDev::get_assoc_list)\n- [.get_by_association()](IterableDev::get_by_association)\n\n"]
2472    pub fn op_dev_get_dump(self) -> OpDevGetDump<'buf> {
2473        let mut res = OpDevGetDump::new(self);
2474        res.request
2475            .do_writeback(res.protocol(), "op-dev-get-dump", OpDevGetDump::lookup);
2476        res
2477    }
2478    #[doc = "Get / dump information about PSP capable devices on the system.\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n\nReply attributes:\n- [.get_id()](IterableDev::get_id)\n- [.get_ifindex()](IterableDev::get_ifindex)\n- [.get_psp_versions_cap()](IterableDev::get_psp_versions_cap)\n- [.get_psp_versions_ena()](IterableDev::get_psp_versions_ena)\n- [.get_assoc_list()](IterableDev::get_assoc_list)\n- [.get_by_association()](IterableDev::get_by_association)\n\n"]
2479    pub fn op_dev_get_do(self) -> OpDevGetDo<'buf> {
2480        let mut res = OpDevGetDo::new(self);
2481        res.request
2482            .do_writeback(res.protocol(), "op-dev-get-do", OpDevGetDo::lookup);
2483        res
2484    }
2485    #[doc = "Set the configuration of a PSP device.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n- [.push_psp_versions_ena()](PushDev::push_psp_versions_ena)\n\n"]
2486    pub fn op_dev_set_do(self) -> OpDevSetDo<'buf> {
2487        let mut res = OpDevSetDo::new(self);
2488        res.request
2489            .do_writeback(res.protocol(), "op-dev-set-do", OpDevSetDo::lookup);
2490        res
2491    }
2492    #[doc = "Rotate the device key.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n\nReply attributes:\n- [.get_id()](IterableDev::get_id)\n\n"]
2493    pub fn op_key_rotate_do(self) -> OpKeyRotateDo<'buf> {
2494        let mut res = OpKeyRotateDo::new(self);
2495        res.request
2496            .do_writeback(res.protocol(), "op-key-rotate-do", OpKeyRotateDo::lookup);
2497        res
2498    }
2499    #[doc = "Allocate a new Rx key + SPI pair, associate it with a socket.\n\nRequest attributes:\n- [.push_dev_id()](PushAssoc::push_dev_id)\n- [.push_version()](PushAssoc::push_version)\n- [.push_sock_fd()](PushAssoc::push_sock_fd)\n\nReply attributes:\n- [.get_dev_id()](IterableAssoc::get_dev_id)\n- [.get_rx_key()](IterableAssoc::get_rx_key)\n\n"]
2500    pub fn op_rx_assoc_do(self) -> OpRxAssocDo<'buf> {
2501        let mut res = OpRxAssocDo::new(self);
2502        res.request
2503            .do_writeback(res.protocol(), "op-rx-assoc-do", OpRxAssocDo::lookup);
2504        res
2505    }
2506    #[doc = "Add a PSP Tx association.\n\nRequest attributes:\n- [.push_dev_id()](PushAssoc::push_dev_id)\n- [.push_version()](PushAssoc::push_version)\n- [.nested_tx_key()](PushAssoc::nested_tx_key)\n- [.push_sock_fd()](PushAssoc::push_sock_fd)\n\n"]
2507    pub fn op_tx_assoc_do(self) -> OpTxAssocDo<'buf> {
2508        let mut res = OpTxAssocDo::new(self);
2509        res.request
2510            .do_writeback(res.protocol(), "op-tx-assoc-do", OpTxAssocDo::lookup);
2511        res
2512    }
2513    #[doc = "Get device statistics.\n\nReply attributes:\n- [.get_dev_id()](IterableStats::get_dev_id)\n- [.get_key_rotations()](IterableStats::get_key_rotations)\n- [.get_stale_events()](IterableStats::get_stale_events)\n- [.get_rx_packets()](IterableStats::get_rx_packets)\n- [.get_rx_bytes()](IterableStats::get_rx_bytes)\n- [.get_rx_auth_fail()](IterableStats::get_rx_auth_fail)\n- [.get_rx_error()](IterableStats::get_rx_error)\n- [.get_rx_bad()](IterableStats::get_rx_bad)\n- [.get_tx_packets()](IterableStats::get_tx_packets)\n- [.get_tx_bytes()](IterableStats::get_tx_bytes)\n- [.get_tx_error()](IterableStats::get_tx_error)\n\n"]
2514    pub fn op_get_stats_dump(self) -> OpGetStatsDump<'buf> {
2515        let mut res = OpGetStatsDump::new(self);
2516        res.request
2517            .do_writeback(res.protocol(), "op-get-stats-dump", OpGetStatsDump::lookup);
2518        res
2519    }
2520    #[doc = "Get device statistics.\n\nRequest attributes:\n- [.push_dev_id()](PushStats::push_dev_id)\n\nReply attributes:\n- [.get_dev_id()](IterableStats::get_dev_id)\n- [.get_key_rotations()](IterableStats::get_key_rotations)\n- [.get_stale_events()](IterableStats::get_stale_events)\n- [.get_rx_packets()](IterableStats::get_rx_packets)\n- [.get_rx_bytes()](IterableStats::get_rx_bytes)\n- [.get_rx_auth_fail()](IterableStats::get_rx_auth_fail)\n- [.get_rx_error()](IterableStats::get_rx_error)\n- [.get_rx_bad()](IterableStats::get_rx_bad)\n- [.get_tx_packets()](IterableStats::get_tx_packets)\n- [.get_tx_bytes()](IterableStats::get_tx_bytes)\n- [.get_tx_error()](IterableStats::get_tx_error)\n\n"]
2521    pub fn op_get_stats_do(self) -> OpGetStatsDo<'buf> {
2522        let mut res = OpGetStatsDo::new(self);
2523        res.request
2524            .do_writeback(res.protocol(), "op-get-stats-do", OpGetStatsDo::lookup);
2525        res
2526    }
2527    #[doc = "Associate a network device with a PSP device.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n- [.push_ifindex()](PushDev::push_ifindex)\n- [.push_nsid()](PushDev::push_nsid)\n\n"]
2528    pub fn op_dev_assoc_do(self) -> OpDevAssocDo<'buf> {
2529        let mut res = OpDevAssocDo::new(self);
2530        res.request
2531            .do_writeback(res.protocol(), "op-dev-assoc-do", OpDevAssocDo::lookup);
2532        res
2533    }
2534    #[doc = "Disassociate a network device from a PSP device.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_id()](PushDev::push_id)\n- [.push_ifindex()](PushDev::push_ifindex)\n- [.push_nsid()](PushDev::push_nsid)\n\n"]
2535    pub fn op_dev_disassoc_do(self) -> OpDevDisassocDo<'buf> {
2536        let mut res = OpDevDisassocDo::new(self);
2537        res.request.do_writeback(
2538            res.protocol(),
2539            "op-dev-disassoc-do",
2540            OpDevDisassocDo::lookup,
2541        );
2542        res
2543    }
2544}
2545#[cfg(test)]
2546mod generated_tests {
2547    use super::*;
2548    #[test]
2549    fn tests() {
2550        let _ = IterableAssoc::get_dev_id;
2551        let _ = IterableAssoc::get_rx_key;
2552        let _ = IterableDev::get_assoc_list;
2553        let _ = IterableDev::get_by_association;
2554        let _ = IterableDev::get_id;
2555        let _ = IterableDev::get_ifindex;
2556        let _ = IterableDev::get_psp_versions_cap;
2557        let _ = IterableDev::get_psp_versions_ena;
2558        let _ = IterableStats::get_dev_id;
2559        let _ = IterableStats::get_key_rotations;
2560        let _ = IterableStats::get_rx_auth_fail;
2561        let _ = IterableStats::get_rx_bad;
2562        let _ = IterableStats::get_rx_bytes;
2563        let _ = IterableStats::get_rx_error;
2564        let _ = IterableStats::get_rx_packets;
2565        let _ = IterableStats::get_stale_events;
2566        let _ = IterableStats::get_tx_bytes;
2567        let _ = IterableStats::get_tx_error;
2568        let _ = IterableStats::get_tx_packets;
2569        let _ = OpDevAddNotif;
2570        let _ = OpDevChangeNotif;
2571        let _ = OpDevDelNotif;
2572        let _ = OpKeyRotateNotif;
2573        let _ = PushAssoc::<&mut Vec<u8>>::nested_tx_key;
2574        let _ = PushAssoc::<&mut Vec<u8>>::push_dev_id;
2575        let _ = PushAssoc::<&mut Vec<u8>>::push_sock_fd;
2576        let _ = PushAssoc::<&mut Vec<u8>>::push_version;
2577        let _ = PushDev::<&mut Vec<u8>>::push_id;
2578        let _ = PushDev::<&mut Vec<u8>>::push_ifindex;
2579        let _ = PushDev::<&mut Vec<u8>>::push_nsid;
2580        let _ = PushDev::<&mut Vec<u8>>::push_psp_versions_ena;
2581        let _ = PushStats::<&mut Vec<u8>>::push_dev_id;
2582    }
2583}