Skip to main content

netlink_packet_netfilter/none/
message.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4    DecodeError, DefaultNla, Emitable, ErrorContext as _, ParseableParametrized,
5};
6
7use crate::nlas::default_nlas;
8
9#[derive(Debug, PartialEq, Eq, Clone)]
10#[non_exhaustive]
11pub enum ControlMessage {
12    BatchBegin,
13    BatchEnd,
14    Other {
15        message_type: u8,
16        attributes: Vec<DefaultNla>,
17    },
18}
19
20// Defined in Linux kernel: include/uapi/linux/netfilter/nfnetlink.h
21const NFNL_MSG_BATCH_BEGIN: u8 = 16;
22const NFNL_MSG_BATCH_END: u8 = 17;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25#[non_exhaustive]
26pub enum ControlMessageType {
27    BatchBegin,
28    BatchEnd,
29    Other(u8),
30}
31
32impl From<u8> for ControlMessageType {
33    fn from(value: u8) -> Self {
34        match value {
35            NFNL_MSG_BATCH_BEGIN => Self::BatchBegin,
36            NFNL_MSG_BATCH_END => Self::BatchEnd,
37            v => Self::Other(v),
38        }
39    }
40}
41
42impl From<ControlMessageType> for u8 {
43    fn from(value: ControlMessageType) -> Self {
44        match value {
45            ControlMessageType::BatchBegin => NFNL_MSG_BATCH_BEGIN,
46            ControlMessageType::BatchEnd => NFNL_MSG_BATCH_END,
47            ControlMessageType::Other(v) => v,
48        }
49    }
50}
51
52impl ControlMessage {
53    pub fn message_type(&self) -> ControlMessageType {
54        match self {
55            Self::BatchBegin => ControlMessageType::BatchBegin,
56            Self::BatchEnd => ControlMessageType::BatchEnd,
57            Self::Other { message_type, .. } => (*message_type).into(),
58        }
59    }
60}
61
62impl Emitable for ControlMessage {
63    fn buffer_len(&self) -> usize {
64        match self {
65            Self::BatchBegin | Self::BatchEnd => 0,
66            Self::Other { attributes, .. } => {
67                attributes.as_slice().buffer_len()
68            }
69        }
70    }
71
72    fn emit(&self, buffer: &mut [u8]) {
73        match self {
74            Self::BatchBegin | Self::BatchEnd => {}
75            Self::Other { attributes, .. } => {
76                attributes.as_slice().emit(buffer)
77            }
78        }
79    }
80}
81
82impl ParseableParametrized<[u8], u8> for ControlMessage {
83    fn parse_with_param(
84        buf: &[u8],
85        message_type: u8,
86    ) -> Result<Self, DecodeError> {
87        Ok(match ControlMessageType::from(message_type) {
88            ControlMessageType::BatchBegin => Self::BatchBegin,
89            ControlMessageType::BatchEnd => Self::BatchEnd,
90            ControlMessageType::Other(_) => {
91                let attributes =
92                    default_nlas(buf).context("failed to parse message nla")?;
93                Self::Other {
94                    message_type,
95                    attributes,
96                }
97            }
98        })
99    }
100}