1use crate as neli;
17
18use std::io::Cursor;
19
20use crate::{
21 attr::{AttrHandle, AttrHandleMut, Attribute},
22 consts::genl::{Cmd, NlAttrType},
23 err::{DeError, SerError},
24 types::{Buffer, GenlBuffer},
25 FromBytes, FromBytesWithInput, Header, Size, ToBytes, TypeSize,
26};
27
28#[derive(Debug, PartialEq, Eq, Size, ToBytes, FromBytes)]
30pub struct NoUserHeader;
31
32impl TypeSize for NoUserHeader {
33 fn type_size() -> usize {
34 0
35 }
36}
37
38#[derive(Debug, PartialEq, Eq, Size, ToBytes, FromBytesWithInput, Header)]
40#[neli(to_bytes_bound = "C: Cmd")]
41#[neli(to_bytes_bound = "T: NlAttrType")]
42#[neli(from_bytes_bound = "C: Cmd + TypeSize")]
43#[neli(from_bytes_bound = "T: NlAttrType")]
44#[neli(header_bound = "C: TypeSize")]
45#[neli(from_bytes_bound = "H: TypeSize + FromBytes")]
46#[neli(header_bound = "H: TypeSize")]
47pub struct Genlmsghdr<C, T, H = NoUserHeader> {
48 pub cmd: C,
50 pub version: u8,
52 reserved: u16,
53 pub header: H,
56 #[neli(input = "input - Self::header_size()")]
58 attrs: GenlBuffer<T, Buffer>,
59}
60
61impl<C, T> Genlmsghdr<C, T>
62where
63 C: Cmd,
64 T: NlAttrType,
65{
66 pub fn new(cmd: C, version: u8, attrs: GenlBuffer<T, Buffer>) -> Self {
68 Genlmsghdr {
69 cmd,
70 version,
71 reserved: 0,
72 header: NoUserHeader,
73 attrs,
74 }
75 }
76
77 pub fn get_attr_handle(&self) -> AttrHandle<GenlBuffer<T, Buffer>, Nlattr<T, Buffer>> {
79 self.attrs.get_attr_handle()
80 }
81
82 pub fn get_attr_handle_mut(
84 &mut self,
85 ) -> AttrHandleMut<GenlBuffer<T, Buffer>, Nlattr<T, Buffer>> {
86 self.attrs.get_attr_handle_mut()
87 }
88}
89
90impl<C, T, H> Genlmsghdr<C, T, H> {
91 pub fn new_with_user_header(
93 cmd: C,
94 version: u8,
95 header: H,
96 attrs: GenlBuffer<T, Buffer>,
97 ) -> Self {
98 Genlmsghdr {
99 cmd,
100 version,
101 reserved: 0,
102 header,
103 attrs,
104 }
105 }
106}
107
108#[derive(Debug, PartialEq, Eq, Clone)]
111pub struct AttrType<T> {
112 pub nla_nested: bool,
114 pub nla_network_order: bool,
116 pub nla_type: T,
118}
119
120impl<T> Size for AttrType<T>
121where
122 T: Size,
123{
124 fn unpadded_size(&self) -> usize {
125 self.nla_type.unpadded_size()
126 }
127}
128
129impl<T> TypeSize for AttrType<T>
130where
131 T: TypeSize,
132{
133 fn type_size() -> usize {
134 T::type_size()
135 }
136}
137
138impl<T> ToBytes for AttrType<T>
139where
140 T: NlAttrType,
141{
142 fn to_bytes(&self, buffer: &mut Cursor<Vec<u8>>) -> Result<(), SerError> {
143 let int: u16 = self.into();
144 int.to_bytes(buffer)
145 }
146}
147
148impl<'lt, T> FromBytes<'lt> for AttrType<T>
149where
150 T: NlAttrType,
151{
152 fn from_bytes(buffer: &mut Cursor<&'lt [u8]>) -> Result<Self, DeError> {
153 let int = u16::from_bytes(buffer)?;
154 Ok(AttrType::from(int))
155 }
156}
157
158impl<T> From<AttrType<T>> for u16
159where
160 T: NlAttrType,
161{
162 fn from(v: AttrType<T>) -> Self {
163 let mut int: u16 = v.nla_type.into();
164 int |= u16::from(v.nla_nested) << 15;
165 int |= u16::from(v.nla_network_order) << 14;
166 int
167 }
168}
169
170impl<'a, T> From<&'a AttrType<T>> for u16
171where
172 T: NlAttrType,
173{
174 fn from(v: &'a AttrType<T>) -> Self {
175 let mut int: u16 = v.nla_type.into();
176 int |= u16::from(v.nla_nested) << 15;
177 int |= u16::from(v.nla_network_order) << 14;
178 int
179 }
180}
181
182impl<T> From<u16> for AttrType<T>
183where
184 T: NlAttrType,
185{
186 fn from(int: u16) -> Self {
187 AttrType {
188 nla_nested: (int & 1 << 15) == (1 << 15),
189 nla_network_order: (int & 1 << 14) == (1 << 14),
190 nla_type: T::from(!(3 << 14) & int),
191 }
192 }
193}
194
195#[derive(Debug, PartialEq, Eq, Size, FromBytes, ToBytes, Header)]
197#[neli(from_bytes_bound = "T: NlAttrType")]
198#[neli(from_bytes_bound = "P: FromBytesWithInput<Input = usize>")]
199#[neli(to_bytes_bound = "T: NlAttrType")]
200#[neli(header_bound = "T: TypeSize")]
201#[neli(padding)]
202pub struct Nlattr<T, P> {
203 pub nla_len: u16,
205 pub nla_type: AttrType<T>,
207 #[neli(input = "nla_len as usize - Self::header_size()")]
209 pub nla_payload: P,
210}
211
212impl<T> Nlattr<T, Buffer>
213where
214 T: NlAttrType,
215{
216 pub fn new<P>(
219 nla_nested: bool,
220 nla_network_order: bool,
221 nla_type: T,
222 nla_payload: P,
223 ) -> Result<Self, SerError>
224 where
225 P: Size + ToBytes,
226 {
227 let mut attr = Nlattr {
228 nla_len: Self::header_size() as u16,
229 nla_type: AttrType {
230 nla_nested,
231 nla_network_order,
232 nla_type,
233 },
234 nla_payload: Buffer::new(),
235 };
236 attr.set_payload(&nla_payload)?;
237 Ok(attr)
238 }
239
240 pub fn add_nested_attribute<TT, P>(&mut self, attr: &Nlattr<TT, P>) -> Result<(), SerError>
242 where
243 TT: NlAttrType,
244 P: ToBytes,
245 {
246 let mut buffer = Cursor::new(Vec::new());
247 attr.to_bytes(&mut buffer)?;
248
249 self.nla_payload.extend_from_slice(buffer.get_ref());
250 self.nla_len += buffer.get_ref().len() as u16;
251 Ok(())
252 }
253
254 pub fn get_attr_handle<R>(&self) -> Result<GenlAttrHandle<R>, DeError>
256 where
257 R: NlAttrType,
258 {
259 Ok(AttrHandle::new(GenlBuffer::from_bytes_with_input(
260 &mut Cursor::new(self.nla_payload.as_ref()),
261 self.nla_payload.unpadded_size(),
262 )?))
263 }
264
265 pub fn get_attr_handle_mut<R>(&mut self) -> Result<GenlAttrHandleMut<R>, DeError>
267 where
268 R: NlAttrType,
269 {
270 Ok(AttrHandleMut::new(GenlBuffer::from_bytes_with_input(
271 &mut Cursor::new(self.nla_payload.as_ref()),
272 self.nla_payload.unpadded_size(),
273 )?))
274 }
275}
276
277impl<T> Attribute<T> for Nlattr<T, Buffer>
278where
279 T: NlAttrType,
280{
281 fn payload(&self) -> &Buffer {
282 &self.nla_payload
283 }
284
285 fn set_payload<P>(&mut self, payload: &P) -> Result<(), SerError>
286 where
287 P: Size + ToBytes,
288 {
289 let mut buffer = Cursor::new(Vec::new());
290 payload.to_bytes(&mut buffer)?;
291
292 self.nla_len -= self.nla_payload.unpadded_size() as u16;
294 self.nla_len += buffer.get_ref().len() as u16;
295
296 self.nla_payload = Buffer::from(buffer.into_inner());
297
298 Ok(())
299 }
300}
301
302type GenlAttrHandle<'a, T> = AttrHandle<'a, GenlBuffer<T, Buffer>, Nlattr<T, Buffer>>;
303type GenlAttrHandleMut<'a, T> = AttrHandleMut<'a, GenlBuffer<T, Buffer>, Nlattr<T, Buffer>>;
304
305impl<'a, T> AttrHandle<'a, GenlBuffer<T, Buffer>, Nlattr<T, Buffer>>
306where
307 T: NlAttrType,
308{
309 pub fn get_nested_attributes<S>(&mut self, subattr: T) -> Result<GenlAttrHandle<S>, DeError>
312 where
313 S: NlAttrType,
314 {
315 let attr = self
316 .get_attribute(subattr)
317 .ok_or_else(|| DeError::new("Couldn't find specified attribute"))?;
318 Ok(AttrHandle::new(GenlBuffer::from_bytes_with_input(
319 &mut Cursor::new(attr.nla_payload.as_ref()),
320 attr.nla_payload.unpadded_size(),
321 )?))
322 }
323
324 pub fn get_attribute(&self, t: T) -> Option<&Nlattr<T, Buffer>> {
326 self.get_attrs()
327 .iter()
328 .find(|item| item.nla_type.nla_type == t)
329 }
330
331 pub fn get_attr_payload_as<'b, R>(&'b self, attr: T) -> Result<R, DeError>
333 where
334 R: FromBytes<'b>,
335 {
336 match self.get_attribute(attr) {
337 Some(a) => a.get_payload_as::<R>(),
338 _ => Err(DeError::new("Failed to find specified attribute")),
339 }
340 }
341
342 pub fn get_attr_payload_as_with_len<'b, R>(&'b self, attr: T) -> Result<R, DeError>
345 where
346 R: FromBytesWithInput<'b, Input = usize>,
347 {
348 match self.get_attribute(attr) {
349 Some(a) => a.get_payload_as_with_len::<R>(),
350 _ => Err(DeError::new("Failed to find specified attribute")),
351 }
352 }
353}