netlink_packet_generic/ctrl/nlas/
oppolicy.rs1use 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}