Skip to main content

netlink_bindings/psp/
mod.rs

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