netlink_packet/netlink/
error.rs

1use crate::{DecodeError, Emitable, Field, Parseable, Rest};
2use byteorder::{ByteOrder, NativeEndian};
3use std::mem::size_of;
4
5const CODE: Field = 0..4;
6const PAYLOAD: Rest = 4..;
7
8#[derive(Debug, PartialEq, Eq, Clone)]
9pub struct ErrorBuffer<T> {
10    buffer: T,
11}
12
13impl<T: AsRef<[u8]>> ErrorBuffer<T> {
14    pub fn new(buffer: T) -> ErrorBuffer<T> {
15        ErrorBuffer { buffer }
16    }
17
18    /// Consume the packet, returning the underlying buffer.
19    pub fn into_inner(self) -> T {
20        self.buffer
21    }
22
23    /// Return the error code
24    pub fn code(&self) -> i32 {
25        let data = self.buffer.as_ref();
26        NativeEndian::read_i32(&data[CODE])
27    }
28}
29
30impl<'a, T: AsRef<[u8]> + ?Sized> ErrorBuffer<&'a T> {
31    /// Return a pointer to the payload.
32    pub fn payload(&self) -> &'a [u8] {
33        let data = self.buffer.as_ref();
34        &data[PAYLOAD]
35    }
36}
37
38impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> ErrorBuffer<&'a mut T> {
39    /// Return a mutable pointer to the payload.
40    pub fn payload_mut(&mut self) -> &mut [u8] {
41        let data = self.buffer.as_mut();
42        &mut data[PAYLOAD]
43    }
44}
45
46impl<T: AsRef<[u8]> + AsMut<[u8]>> ErrorBuffer<T> {
47    /// set the error code field
48    pub fn set_code(&mut self, value: i32) {
49        let data = self.buffer.as_mut();
50        NativeEndian::write_i32(&mut data[CODE], value)
51    }
52}
53
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct ErrorMessage {
56    pub code: i32,
57    pub header: Vec<u8>,
58}
59
60pub type AckMessage = ErrorMessage;
61
62impl Emitable for ErrorMessage {
63    fn buffer_len(&self) -> usize {
64        size_of::<i32>() + self.header.len()
65    }
66    fn emit(&self, buffer: &mut [u8]) {
67        let mut buffer = ErrorBuffer::new(buffer);
68        buffer.set_code(self.code);
69        buffer.payload_mut().copy_from_slice(&self.header)
70    }
71}
72
73impl<'buffer, T: AsRef<[u8]> + 'buffer> Parseable<ErrorMessage> for ErrorBuffer<&'buffer T> {
74    fn parse(&self) -> Result<ErrorMessage, DecodeError> {
75        // FIXME: The payload of an error is basically a truncated packet, which requires custom
76        // logic to parse correctly. For now we just return it as a Vec<u8>
77        // let header: NetlinkHeader = {
78        //     NetlinkBuffer::new_checked(self.payload())
79        //         .context("failed to parse netlink header")?
80        //         .parse()
81        //         .context("failed to parse nelink header")?
82        // };
83        Ok(ErrorMessage {
84            code: self.code(),
85            header: self.payload().to_vec(),
86        })
87    }
88}