netlink_packet_generic/ctrl/nlas/
ops.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    Parseable,
7};
8use std::{mem::size_of_val, ops::Deref};
9
10pub struct OpList(Vec<Op>);
11
12impl Deref for OpList {
13    type Target = Vec<Op>;
14
15    fn deref(&self) -> &Self::Target {
16        &self.0
17    }
18}
19
20impl From<&Vec<Vec<OpAttrs>>> for OpList {
21    fn from(ops: &Vec<Vec<OpAttrs>>) -> Self {
22        Self(
23            ops.iter()
24                .cloned()
25                .enumerate()
26                .map(|(index, nlas)| Op {
27                    index: index as u16,
28                    nlas,
29                })
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) => emit_u32(buffer, *v).unwrap(),
82            Flags(v) => emit_u32(buffer, *v).unwrap(),
83        }
84    }
85}
86
87impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for OpAttrs {
88    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
89        let payload = buf.value();
90        Ok(match buf.kind() {
91            CTRL_ATTR_OP_ID => Self::Id(
92                parse_u32(payload).context("invalid CTRL_ATTR_OP_ID value")?,
93            ),
94            CTRL_ATTR_OP_FLAGS => Self::Flags(
95                parse_u32(payload)
96                    .context("invalid CTRL_ATTR_OP_FLAGS value")?,
97            ),
98            kind => {
99                return Err(DecodeError::from(format!(
100                    "Unknown NLA type: {kind}"
101                )))
102            }
103        })
104    }
105}