netlink-packet-netfilter 0.4.0

netlink packet types for the netfilter subprotocol
Documentation
// SPDX-License-Identifier: MIT

use netlink_packet_core::{
    DecodeError, DefaultNla, Emitable, Parseable, ParseableParametrized,
};

use crate::nflog::{ConfigNla, PacketNla};
use crate::nlas::parse_all_nlas;

#[derive(Debug, PartialEq, Eq, Clone)]
#[non_exhaustive]
pub enum ULogMessage {
    Config(Vec<ConfigNla>),
    Packet(Vec<PacketNla>),
    Other {
        message_type: u8,
        nlas: Vec<DefaultNla>,
    },
}

const NFULNL_MSG_CONFIG: u8 = libc::NFULNL_MSG_CONFIG as u8;
const NFULNL_MSG_PACKET: u8 = libc::NFULNL_MSG_PACKET as u8;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[non_exhaustive]
pub enum ULogMessageType {
    Config,
    Packet,
    Other(u8),
}

impl From<u8> for ULogMessageType {
    fn from(value: u8) -> Self {
        match value {
            NFULNL_MSG_CONFIG => Self::Config,
            NFULNL_MSG_PACKET => Self::Packet,
            v => Self::Other(v),
        }
    }
}

impl From<ULogMessageType> for u8 {
    fn from(value: ULogMessageType) -> Self {
        match value {
            ULogMessageType::Config => NFULNL_MSG_CONFIG,
            ULogMessageType::Packet => NFULNL_MSG_PACKET,
            ULogMessageType::Other(v) => v,
        }
    }
}

impl ULogMessage {
    pub fn message_type(&self) -> ULogMessageType {
        match self {
            ULogMessage::Config(_) => ULogMessageType::Config,
            ULogMessage::Packet(_) => ULogMessageType::Packet,
            ULogMessage::Other { message_type, .. } => (*message_type).into(),
        }
    }
}

impl Emitable for ULogMessage {
    fn buffer_len(&self) -> usize {
        match self {
            ULogMessage::Config(nlas) => nlas.as_slice().buffer_len(),
            ULogMessage::Packet(nlas) => nlas.as_slice().buffer_len(),
            ULogMessage::Other { nlas, .. } => nlas.as_slice().buffer_len(),
        }
    }

    fn emit(&self, buffer: &mut [u8]) {
        match self {
            ULogMessage::Config(nlas) => nlas.as_slice().emit(buffer),
            ULogMessage::Packet(nlas) => nlas.as_slice().emit(buffer),
            ULogMessage::Other { nlas, .. } => nlas.as_slice().emit(buffer),
        };
    }
}

impl ParseableParametrized<[u8], u8> for ULogMessage {
    fn parse_with_param(
        buf: &[u8],
        message_type: u8,
    ) -> Result<Self, DecodeError> {
        Ok(match ULogMessageType::from(message_type) {
            ULogMessageType::Config => {
                let nlas =
                    parse_all_nlas(buf, |nla_buf| ConfigNla::parse(&nla_buf))?;
                ULogMessage::Config(nlas)
            }
            ULogMessageType::Packet => {
                let nlas =
                    parse_all_nlas(buf, |nla_buf| PacketNla::parse(&nla_buf))?;
                ULogMessage::Packet(nlas)
            }
            ULogMessageType::Other(message_type) => ULogMessage::Other {
                message_type,
                nlas: crate::nlas::default_nlas(buf)?,
            },
        })
    }
}