netlink_packet_generic/ctrl/nlas/
ops.rs
1use 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}