netlink_packet_sock_diag/
buffer.rs1use 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}