netlink_packet_generic/ctrl/nlas/
oppolicy.rs

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