netlink_packet_netfilter/
buffer.rs

1// SPDX-License-Identifier: MIT
2
3use crate::{
4    message::{
5        NetfilterHeader, NetfilterMessage, NetfilterMessageInner,
6        NETFILTER_HEADER_LEN,
7    },
8    nflog::NfLogMessage,
9};
10use anyhow::Context;
11use netlink_packet_utils::{
12    buffer,
13    nla::{DefaultNla, NlaBuffer, NlasIterator},
14    DecodeError, Parseable, ParseableParametrized,
15};
16
17buffer!(NetfilterBuffer(NETFILTER_HEADER_LEN) {
18    header: (slice, ..NETFILTER_HEADER_LEN),
19    payload: (slice, NETFILTER_HEADER_LEN..),
20});
21
22impl<'a, T: AsRef<[u8]> + ?Sized> NetfilterBuffer<&'a T> {
23    pub fn nlas(
24        &self,
25    ) -> impl Iterator<Item = Result<NlaBuffer<&'a [u8]>, DecodeError>> {
26        NlasIterator::new(self.payload())
27    }
28
29    pub fn parse_all_nlas<F, U>(&self, f: F) -> Result<Vec<U>, DecodeError>
30    where
31        F: Fn(NlaBuffer<&[u8]>) -> Result<U, DecodeError>,
32    {
33        Ok(self
34            .nlas()
35            .map(|buf| f(buf?))
36            .collect::<Result<Vec<_>, _>>()
37            .context("failed to parse NLAs")?)
38    }
39
40    pub fn default_nlas(&self) -> Result<Vec<DefaultNla>, DecodeError> {
41        self.parse_all_nlas(|buf| DefaultNla::parse(&buf))
42    }
43}
44
45impl<'a, T: AsRef<[u8]> + ?Sized>
46    ParseableParametrized<NetfilterBuffer<&'a T>, u16> for NetfilterMessage
47{
48    fn parse_with_param(
49        buf: &NetfilterBuffer<&'a T>,
50        message_type: u16,
51    ) -> Result<Self, DecodeError> {
52        let header_buf =
53            crate::message::NetfilterHeaderBuffer::new(buf.inner());
54        let header = NetfilterHeader::parse(&header_buf)
55            .context("failed to parse netfilter header")?;
56        let subsys = (message_type >> 8) as u8;
57        let message_type = message_type as u8;
58        let inner = match subsys {
59            NfLogMessage::SUBSYS => NetfilterMessageInner::NfLog(
60                NfLogMessage::parse_with_param(buf, message_type)
61                    .context("failed to parse nflog payload")?,
62            ),
63            _ => NetfilterMessageInner::Other {
64                subsys,
65                message_type,
66                nlas: buf.default_nlas()?,
67            },
68        };
69        Ok(NetfilterMessage::new(header, inner))
70    }
71}