netlink_packet_sock_diag/
buffer.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use netlink_packet_utils::DecodeError;
5use netlink_packet_utils::traits::{Parseable, ParseableParametrized};
6
7use crate::constants::*;
8use crate::{SockDiagRequest, SockDiagResponse, inet, unix};
9
10const BUF_MIN_LEN: usize = 2;
11
12pub struct SockDiagBuffer<T> {
13    buffer: T,
14}
15
16impl<T: AsRef<[u8]>> SockDiagBuffer<T> {
17    pub(crate) fn new_unchecked(buffer: T) -> SockDiagBuffer<T> {
18        SockDiagBuffer { buffer }
19    }
20
21    pub fn length(&self) -> usize {
22        self.buffer.as_ref().len()
23    }
24
25    pub fn new(buffer: T) -> Result<Self, DecodeError> {
26        let packet = Self::new_unchecked(buffer);
27        packet.check_len()?;
28        Ok(packet)
29    }
30
31    pub(crate) fn check_len(&self) -> Result<(), DecodeError> {
32        let len = self.buffer.as_ref().len();
33        if len < BUF_MIN_LEN {
34            return Err(format!(
35                "invalid buffer: length is {len} but packets are at least {BUF_MIN_LEN} bytes"
36            )
37            .into());
38        }
39        Ok(())
40    }
41
42    pub(crate) fn family(&self) -> u8 {
43        self.buffer.as_ref()[0]
44    }
45}
46
47impl<'a, T: AsRef<[u8]> + ?Sized> SockDiagBuffer<&'a T> {
48    pub fn inner(&self) -> &'a [u8] {
49        self.buffer.as_ref()
50    }
51}
52
53impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> SockDiagBuffer<&'a mut T> {
54    pub fn inner_mut(&mut self) -> &mut [u8] {
55        self.buffer.as_mut()
56    }
57}
58
59impl<'a, T: AsRef<[u8]>> ParseableParametrized<SockDiagBuffer<&'a T>, u16> for SockDiagRequest {
60    type Error = DecodeError;
61    fn parse_with_param(
62        buf: &SockDiagBuffer<&'a T>,
63        message_type: u16,
64    ) -> Result<Self, DecodeError> {
65        use crate::SockDiagRequest::*;
66        buf.check_len()?;
67        let message = match (message_type, buf.family()) {
68            (SOCK_DIAG_BY_FAMILY, AF_INET | AF_INET6) => {
69                let err = "invalid AF_INET/AF_INET6 request";
70                let buf = inet::InetRequestBuffer::new(buf.inner()).context(err)?;
71                InetRequest(inet::InetRequest::parse(&buf).context(err)?)
72            }
73            (SOCK_DIAG_BY_FAMILY, AF_UNIX) => {
74                let err = "invalid AF_UNIX request";
75                let buf = unix::UnixRequestBuffer::new(buf.inner()).context(err)?;
76                UnixRequest(unix::UnixRequest::parse(&buf).context(err)?)
77            }
78            (SOCK_DIAG_BY_FAMILY, af) => return Err(format!("unknown address family {af}").into()),
79            (SOCK_DESTROY, AF_INET | AF_INET6) => {
80                let err = "invalid AF_INET/AF_INET6 request";
81                let buf = inet::InetRequestBuffer::new(buf.inner()).context(err)?;
82                InetSockDestroy(inet::InetRequest::parse(&buf).context(err)?)
83            }
84            _ => return Err(format!("unknown message type {message_type}").into()),
85        };
86        Ok(message)
87    }
88}
89
90impl<'a, T: AsRef<[u8]>> ParseableParametrized<SockDiagBuffer<&'a T>, u16> for SockDiagResponse {
91    type Error = DecodeError;
92    fn parse_with_param(
93        buf: &SockDiagBuffer<&'a T>,
94        message_type: u16,
95    ) -> Result<Self, DecodeError> {
96        use crate::SockDiagResponse::*;
97        buf.check_len()?;
98        let message = match (message_type, buf.family()) {
99            (SOCK_DIAG_BY_FAMILY, AF_INET | AF_INET6) => {
100                let err = "invalid AF_INET/AF_INET6 response";
101                let buf = inet::InetResponseBuffer::new(buf.inner()).context(err)?;
102                InetResponse(inet::InetResponse::parse(&buf).context(err)?)
103            }
104            (SOCK_DIAG_BY_FAMILY, AF_UNIX) => {
105                let err = "invalid AF_UNIX response";
106                let buf = unix::UnixResponseBuffer::new(buf.inner()).context(err)?;
107                UnixResponse(unix::UnixResponse::parse(&buf).context(err)?)
108            }
109            (SOCK_DIAG_BY_FAMILY, af) => return Err(format!("unknown address family {af}").into()),
110            _ => return Err(format!("unknown message type {message_type}").into()),
111        };
112        Ok(message)
113    }
114}