netlink_packet_generic/ctrl/nlas/
policy.rs

1// SPDX-License-Identifier: MIT
2
3use crate::constants::*;
4use netlink_packet_core::{
5    emit_i64, emit_u32, emit_u64, parse_i64, parse_u32, parse_u64, DecodeError,
6    Emitable, ErrorContext, Nla, NlaBuffer, NlasIterator, Parseable,
7};
8use std::{convert::TryFrom, mem::size_of_val};
9
10// PolicyAttr
11
12#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct PolicyAttr {
14    pub index: u16,
15    pub attr_policy: AttributePolicyAttr,
16}
17
18impl Nla for PolicyAttr {
19    fn value_len(&self) -> usize {
20        self.attr_policy.buffer_len()
21    }
22
23    fn kind(&self) -> u16 {
24        self.index
25    }
26
27    fn emit_value(&self, buffer: &mut [u8]) {
28        self.attr_policy.emit(buffer);
29    }
30
31    fn is_nested(&self) -> bool {
32        true
33    }
34}
35
36impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for PolicyAttr {
37    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
38        let payload = buf.value();
39
40        Ok(Self {
41            index: buf.kind(),
42            attr_policy: AttributePolicyAttr::parse(&NlaBuffer::new(payload))
43                .context("failed to parse PolicyAttr")?,
44        })
45    }
46}
47
48// AttributePolicyAttr
49
50#[derive(Clone, Debug, PartialEq, Eq)]
51pub struct AttributePolicyAttr {
52    pub index: u16,
53    pub policies: Vec<NlPolicyTypeAttrs>,
54}
55
56impl Nla for AttributePolicyAttr {
57    fn value_len(&self) -> usize {
58        self.policies.as_slice().buffer_len()
59    }
60
61    fn kind(&self) -> u16 {
62        self.index
63    }
64
65    fn emit_value(&self, buffer: &mut [u8]) {
66        self.policies.as_slice().emit(buffer);
67    }
68
69    fn is_nested(&self) -> bool {
70        true
71    }
72}
73
74impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
75    for AttributePolicyAttr
76{
77    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
78        let payload = buf.value();
79        let policies = NlasIterator::new(payload)
80            .map(|nla| nla.and_then(|nla| NlPolicyTypeAttrs::parse(&nla)))
81            .collect::<Result<Vec<_>, _>>()
82            .context("failed to parse AttributePolicyAttr")?;
83
84        Ok(Self {
85            index: buf.kind(),
86            policies,
87        })
88    }
89}
90
91// PolicyTypeAttrs
92
93#[derive(Clone, Debug, PartialEq, Eq)]
94pub enum NlPolicyTypeAttrs {
95    Type(NlaType),
96    MinValueSigned(i64),
97    MaxValueSigned(i64),
98    MaxValueUnsigned(u64),
99    MinValueUnsigned(u64),
100    MinLength(u32),
101    MaxLength(u32),
102    PolicyIdx(u32),
103    PolicyMaxType(u32),
104    Bitfield32Mask(u32),
105    Mask(u64),
106}
107
108impl Nla for NlPolicyTypeAttrs {
109    fn value_len(&self) -> usize {
110        use NlPolicyTypeAttrs::*;
111        match self {
112            Type(v) => size_of_val(v),
113            MinValueSigned(v) => size_of_val(v),
114            MaxValueSigned(v) => size_of_val(v),
115            MaxValueUnsigned(v) => size_of_val(v),
116            MinValueUnsigned(v) => size_of_val(v),
117            MinLength(v) => size_of_val(v),
118            MaxLength(v) => size_of_val(v),
119            PolicyIdx(v) => size_of_val(v),
120            PolicyMaxType(v) => size_of_val(v),
121            Bitfield32Mask(v) => size_of_val(v),
122            Mask(v) => size_of_val(v),
123        }
124    }
125
126    fn kind(&self) -> u16 {
127        use NlPolicyTypeAttrs::*;
128        match self {
129            Type(_) => NL_POLICY_TYPE_ATTR_TYPE,
130            MinValueSigned(_) => NL_POLICY_TYPE_ATTR_MIN_VALUE_S,
131            MaxValueSigned(_) => NL_POLICY_TYPE_ATTR_MAX_VALUE_S,
132            MaxValueUnsigned(_) => NL_POLICY_TYPE_ATTR_MIN_VALUE_U,
133            MinValueUnsigned(_) => NL_POLICY_TYPE_ATTR_MAX_VALUE_U,
134            MinLength(_) => NL_POLICY_TYPE_ATTR_MIN_LENGTH,
135            MaxLength(_) => NL_POLICY_TYPE_ATTR_MAX_LENGTH,
136            PolicyIdx(_) => NL_POLICY_TYPE_ATTR_POLICY_IDX,
137            PolicyMaxType(_) => NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
138            Bitfield32Mask(_) => NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,
139            Mask(_) => NL_POLICY_TYPE_ATTR_MASK,
140        }
141    }
142
143    fn emit_value(&self, buffer: &mut [u8]) {
144        use NlPolicyTypeAttrs::*;
145        match self {
146            Type(v) => emit_u32(buffer, u32::from(*v)).unwrap(),
147            MinValueSigned(v) => emit_i64(buffer, *v).unwrap(),
148            MaxValueSigned(v) => emit_i64(buffer, *v).unwrap(),
149            MaxValueUnsigned(v) => emit_u64(buffer, *v).unwrap(),
150            MinValueUnsigned(v) => emit_u64(buffer, *v).unwrap(),
151            MinLength(v) => emit_u32(buffer, *v).unwrap(),
152            MaxLength(v) => emit_u32(buffer, *v).unwrap(),
153            PolicyIdx(v) => emit_u32(buffer, *v).unwrap(),
154            PolicyMaxType(v) => emit_u32(buffer, *v).unwrap(),
155            Bitfield32Mask(v) => emit_u32(buffer, *v).unwrap(),
156            Mask(v) => emit_u64(buffer, *v).unwrap(),
157        }
158    }
159}
160
161impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
162    for NlPolicyTypeAttrs
163{
164    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
165        let payload = buf.value();
166        Ok(match buf.kind() {
167            NL_POLICY_TYPE_ATTR_TYPE => {
168                let value = parse_u32(payload)
169                    .context("invalid NL_POLICY_TYPE_ATTR_TYPE value")?;
170                Self::Type(NlaType::try_from(value)?)
171            }
172            NL_POLICY_TYPE_ATTR_MIN_VALUE_S => Self::MinValueSigned(
173                parse_i64(payload)
174                    .context("invalid NL_POLICY_TYPE_ATTR_MIN_VALUE_S value")?,
175            ),
176            NL_POLICY_TYPE_ATTR_MAX_VALUE_S => Self::MaxValueSigned(
177                parse_i64(payload)
178                    .context("invalid NL_POLICY_TYPE_ATTR_MAX_VALUE_S value")?,
179            ),
180            NL_POLICY_TYPE_ATTR_MIN_VALUE_U => Self::MinValueUnsigned(
181                parse_u64(payload)
182                    .context("invalid NL_POLICY_TYPE_ATTR_MIN_VALUE_U value")?,
183            ),
184            NL_POLICY_TYPE_ATTR_MAX_VALUE_U => Self::MaxValueUnsigned(
185                parse_u64(payload)
186                    .context("invalid NL_POLICY_TYPE_ATTR_MAX_VALUE_U value")?,
187            ),
188            NL_POLICY_TYPE_ATTR_MIN_LENGTH => Self::MinLength(
189                parse_u32(payload)
190                    .context("invalid NL_POLICY_TYPE_ATTR_MIN_LENGTH value")?,
191            ),
192            NL_POLICY_TYPE_ATTR_MAX_LENGTH => Self::MaxLength(
193                parse_u32(payload)
194                    .context("invalid NL_POLICY_TYPE_ATTR_MAX_LENGTH value")?,
195            ),
196            NL_POLICY_TYPE_ATTR_POLICY_IDX => Self::PolicyIdx(
197                parse_u32(payload)
198                    .context("invalid NL_POLICY_TYPE_ATTR_POLICY_IDX value")?,
199            ),
200            NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE => {
201                Self::PolicyMaxType(parse_u32(payload).context(
202                    "invalid NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE value",
203                )?)
204            }
205            NL_POLICY_TYPE_ATTR_BITFIELD32_MASK => {
206                Self::Bitfield32Mask(parse_u32(payload).context(
207                    "invalid NL_POLICY_TYPE_ATTR_BITFIELD32_MASK value",
208                )?)
209            }
210            NL_POLICY_TYPE_ATTR_MASK => Self::Mask(
211                parse_u64(payload)
212                    .context("invalid NL_POLICY_TYPE_ATTR_MASK value")?,
213            ),
214            kind => {
215                return Err(DecodeError::from(format!(
216                    "Unknown NLA type: {kind}"
217                )))
218            }
219        })
220    }
221}
222
223#[derive(Copy, Clone, Debug, PartialEq, Eq)]
224pub enum NlaType {
225    Flag,
226    U8,
227    U16,
228    U32,
229    U64,
230    S8,
231    S16,
232    S32,
233    S64,
234    Binary,
235    String,
236    NulString,
237    Nested,
238    NestedArray,
239    Bitfield32,
240}
241
242impl From<NlaType> for u32 {
243    fn from(nlatype: NlaType) -> u32 {
244        match nlatype {
245            NlaType::Flag => NL_ATTR_TYPE_FLAG,
246            NlaType::U8 => NL_ATTR_TYPE_U8,
247            NlaType::U16 => NL_ATTR_TYPE_U16,
248            NlaType::U32 => NL_ATTR_TYPE_U32,
249            NlaType::U64 => NL_ATTR_TYPE_U64,
250            NlaType::S8 => NL_ATTR_TYPE_S8,
251            NlaType::S16 => NL_ATTR_TYPE_S16,
252            NlaType::S32 => NL_ATTR_TYPE_S32,
253            NlaType::S64 => NL_ATTR_TYPE_S64,
254            NlaType::Binary => NL_ATTR_TYPE_BINARY,
255            NlaType::String => NL_ATTR_TYPE_STRING,
256            NlaType::NulString => NL_ATTR_TYPE_NUL_STRING,
257            NlaType::Nested => NL_ATTR_TYPE_NESTED,
258            NlaType::NestedArray => NL_ATTR_TYPE_NESTED_ARRAY,
259            NlaType::Bitfield32 => NL_ATTR_TYPE_BITFIELD32,
260        }
261    }
262}
263
264impl TryFrom<u32> for NlaType {
265    type Error = DecodeError;
266
267    fn try_from(value: u32) -> Result<Self, Self::Error> {
268        Ok(match value {
269            NL_ATTR_TYPE_FLAG => NlaType::Flag,
270            NL_ATTR_TYPE_U8 => NlaType::U8,
271            NL_ATTR_TYPE_U16 => NlaType::U16,
272            NL_ATTR_TYPE_U32 => NlaType::U32,
273            NL_ATTR_TYPE_U64 => NlaType::U64,
274            NL_ATTR_TYPE_S8 => NlaType::S8,
275            NL_ATTR_TYPE_S16 => NlaType::S16,
276            NL_ATTR_TYPE_S32 => NlaType::S32,
277            NL_ATTR_TYPE_S64 => NlaType::S64,
278            NL_ATTR_TYPE_BINARY => NlaType::Binary,
279            NL_ATTR_TYPE_STRING => NlaType::String,
280            NL_ATTR_TYPE_NUL_STRING => NlaType::NulString,
281            NL_ATTR_TYPE_NESTED => NlaType::Nested,
282            NL_ATTR_TYPE_NESTED_ARRAY => NlaType::NestedArray,
283            NL_ATTR_TYPE_BITFIELD32 => NlaType::Bitfield32,
284            _ => {
285                return Err(DecodeError::from(format!(
286                    "invalid NLA type: {value}"
287                )))
288            }
289        })
290    }
291}