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