netlink_packet_generic/ctrl/nlas/
ops.rs

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