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