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