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