netlink-packet-netfilter 0.4.0

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

use netlink_packet_core::{
    parse_u8, DecodeError, DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer,
    Parseable,
};

use crate::conntrack::attributes::tcp_flags::TCPFlags;

const CTA_PROTOINFO_TCP_STATE: u16 = 1;
const CTA_PROTOINFO_TCP_WSCALE_ORIGINAL: u16 = 2;
const CTA_PROTOINFO_TCP_WSCALE_REPLY: u16 = 3;
const CTA_PROTOINFO_TCP_FLAGS_ORIGINAL: u16 = 4;
const CTA_PROTOINFO_TCP_FLAGS_REPLY: u16 = 5;

#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum ProtoInfoTCP {
    State(u8),
    OriginalWindowScale(u8),
    ReplyWindowScale(u8),
    OriginalFlags(TCPFlags),
    ReplyFlags(TCPFlags),
    Other(DefaultNla),
}
impl Nla for ProtoInfoTCP {
    fn value_len(&self) -> usize {
        match self {
            ProtoInfoTCP::State(attr) => size_of_val(attr),
            ProtoInfoTCP::OriginalWindowScale(attr) => size_of_val(attr),
            ProtoInfoTCP::ReplyWindowScale(attr) => size_of_val(attr),
            ProtoInfoTCP::OriginalFlags(attr) => attr.buffer_len(),
            ProtoInfoTCP::ReplyFlags(attr) => attr.buffer_len(),
            ProtoInfoTCP::Other(attr) => attr.value_len(),
        }
    }

    fn kind(&self) -> u16 {
        match self {
            ProtoInfoTCP::State(_) => CTA_PROTOINFO_TCP_STATE,
            ProtoInfoTCP::OriginalWindowScale(_) => {
                CTA_PROTOINFO_TCP_WSCALE_ORIGINAL
            }
            ProtoInfoTCP::ReplyWindowScale(_) => CTA_PROTOINFO_TCP_WSCALE_REPLY,
            ProtoInfoTCP::OriginalFlags(_) => CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
            ProtoInfoTCP::ReplyFlags(_) => CTA_PROTOINFO_TCP_FLAGS_REPLY,
            ProtoInfoTCP::Other(attr) => attr.kind(),
        }
    }

    fn emit_value(&self, buffer: &mut [u8]) {
        match self {
            ProtoInfoTCP::State(attr) => buffer[0] = *attr,
            ProtoInfoTCP::OriginalWindowScale(attr) => buffer[0] = *attr,
            ProtoInfoTCP::ReplyWindowScale(attr) => buffer[0] = *attr,
            ProtoInfoTCP::OriginalFlags(attr) => attr.emit(buffer),
            ProtoInfoTCP::ReplyFlags(attr) => attr.emit(buffer),
            ProtoInfoTCP::Other(attr) => attr.emit_value(buffer),
        }
    }
}
impl<'buffer, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'buffer T>>
    for ProtoInfoTCP
{
    fn parse(buf: &NlaBuffer<&'buffer T>) -> Result<Self, DecodeError> {
        let kind = buf.kind();
        let payload = buf.value();
        let nla = match kind {
            CTA_PROTOINFO_TCP_STATE => ProtoInfoTCP::State(
                parse_u8(payload)
                    .context("invalid CTA_PROTOINFO_TCP_STATE value")?,
            ),
            CTA_PROTOINFO_TCP_WSCALE_ORIGINAL => {
                ProtoInfoTCP::OriginalWindowScale(parse_u8(payload).context(
                    "invalid CTA_PROTOINFO_TCP_WSCALE_ORIGINAL value",
                )?)
            }
            CTA_PROTOINFO_TCP_WSCALE_REPLY => ProtoInfoTCP::ReplyWindowScale(
                parse_u8(payload)
                    .context("invalid CTA_PROTOINFO_TCP_WSCALE_REPLY value")?,
            ),
            CTA_PROTOINFO_TCP_FLAGS_ORIGINAL => {
                ProtoInfoTCP::OriginalFlags(TCPFlags::parse(payload).context(
                    "invalid CTA_PROTOINFO_TCP_FLAGS_ORIGINAL value",
                )?)
            }
            CTA_PROTOINFO_TCP_FLAGS_REPLY => ProtoInfoTCP::ReplyFlags(
                TCPFlags::parse(payload)
                    .context("invalid CTA_PROTOINFO_TCP_FLAGS_REPLY value")?,
            ),
            _ => ProtoInfoTCP::Other(DefaultNla::parse(buf)?),
        };
        Ok(nla)
    }
}