netlink_packet_generic/ctrl/nlas/
oppolicy.rs

1// SPDX-License-Identifier: MIT
2
3use crate::constants::*;
4use netlink_packet_core::{
5    emit_u32, parse_u32, DecodeError, Emitable, ErrorContext, Nla, NlaBuffer,
6    NlasIterator, Parseable,
7};
8use std::mem::size_of_val;
9
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct OppolicyAttr {
12    pub cmd: u8,
13    pub policy_idx: Vec<OppolicyIndexAttr>,
14}
15
16impl Nla for OppolicyAttr {
17    fn value_len(&self) -> usize {
18        self.policy_idx.as_slice().buffer_len()
19    }
20
21    fn kind(&self) -> u16 {
22        self.cmd as u16
23    }
24
25    fn emit_value(&self, buffer: &mut [u8]) {
26        self.policy_idx.as_slice().emit(buffer);
27    }
28
29    fn is_nested(&self) -> bool {
30        true
31    }
32}
33
34impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for OppolicyAttr {
35    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
36        let payload = buf.value();
37        let policy_idx = NlasIterator::new(payload)
38            .map(|nla| nla.and_then(|nla| OppolicyIndexAttr::parse(&nla)))
39            .collect::<Result<Vec<_>, _>>()
40            .context("failed to parse OppolicyAttr")?;
41
42        Ok(Self {
43            cmd: buf.kind() as u8,
44            policy_idx,
45        })
46    }
47}
48
49#[derive(Clone, Debug, PartialEq, Eq)]
50pub enum OppolicyIndexAttr {
51    Do(u32),
52    Dump(u32),
53}
54
55impl Nla for OppolicyIndexAttr {
56    fn value_len(&self) -> usize {
57        use OppolicyIndexAttr::*;
58        match self {
59            Do(v) => size_of_val(v),
60            Dump(v) => size_of_val(v),
61        }
62    }
63
64    fn kind(&self) -> u16 {
65        use OppolicyIndexAttr::*;
66        match self {
67            Do(_) => CTRL_ATTR_POLICY_DO,
68            Dump(_) => CTRL_ATTR_POLICY_DUMP,
69        }
70    }
71
72    fn emit_value(&self, buffer: &mut [u8]) {
73        use OppolicyIndexAttr::*;
74        match self {
75            Do(v) => emit_u32(buffer, *v).unwrap(),
76            Dump(v) => emit_u32(buffer, *v).unwrap(),
77        }
78    }
79}
80
81impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
82    for OppolicyIndexAttr
83{
84    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
85        let payload = buf.value();
86        Ok(match buf.kind() {
87            CTRL_ATTR_POLICY_DO => Self::Do(
88                parse_u32(payload)
89                    .context("invalid CTRL_ATTR_POLICY_DO value")?,
90            ),
91            CTRL_ATTR_POLICY_DUMP => Self::Dump(
92                parse_u32(payload)
93                    .context("invalid CTRL_ATTR_POLICY_DUMP value")?,
94            ),
95            kind => {
96                return Err(DecodeError::from(format!(
97                    "Unknown NLA type: {kind}"
98                )))
99            }
100        })
101    }
102}