use std::borrow::Cow;
use std::ffi::CStr;
use bytes::{Buf, BufMut};
use libc::{
NFT_MSG_DELCHAIN, NFT_MSG_DELRULE, NFT_MSG_DELTABLE, NFT_MSG_NEWCHAIN, NFT_MSG_NEWRULE,
NFT_MSG_NEWTABLE,
};
use crate::rule::Expr;
use crate::{Command, Encode, Error, Handle, Hook, Message, Policy, ProtoFamily, read_attribute};
use crate::{constants::*, write_attribute};
#[derive(Clone, Debug)]
pub struct AddTable<'a> {
pub name: Cow<'a, CStr>,
pub proto: ProtoFamily,
pub flags: u32,
}
impl Message for AddTable<'_> {
const ID: u16 = NFT_MSG_NEWTABLE as u16;
fn proto(&self) -> ProtoFamily {
self.proto
}
}
impl Encode for AddTable<'_> {
fn encode<B>(&self, mut buf: B)
where
B: BufMut,
{
write_attribute(&mut buf, NFTA_TABLE_NAME, self.name.to_bytes_with_nul());
write_attribute(&mut buf, NFTA_TABLE_FLAGS, &self.flags.to_be_bytes());
}
}
impl<'a> From<AddTable<'a>> for Command<'a> {
#[inline]
fn from(value: AddTable<'a>) -> Self {
Command::AddTable(value)
}
}
#[derive(Clone, Debug)]
pub struct DelTable<'a> {
pub name: Cow<'a, CStr>,
pub proto: ProtoFamily,
}
impl Message for DelTable<'_> {
const ID: u16 = NFT_MSG_DELTABLE as u16;
fn proto(&self) -> ProtoFamily {
self.proto
}
}
impl Encode for DelTable<'_> {
fn encode<B>(&self, mut buf: B)
where
B: BufMut,
{
write_attribute(&mut buf, NFTA_TABLE_NAME, self.name.to_bytes_with_nul());
}
}
impl<'a> From<DelTable<'a>> for Command<'a> {
#[inline]
fn from(value: DelTable<'a>) -> Self {
Command::DelTable(value)
}
}
#[derive(Clone, Debug)]
pub struct AddChain<'a> {
pub table: Cow<'a, CStr>,
pub proto: ProtoFamily,
pub hook: Option<ChainHook>,
pub name: Cow<'a, CStr>,
}
#[derive(Copy, Clone, Debug)]
pub struct ChainHook {
pub hook: Hook,
pub priority: i32,
pub policy: Policy,
}
impl Message for AddChain<'_> {
const ID: u16 = NFT_MSG_NEWCHAIN as u16;
fn proto(&self) -> ProtoFamily {
self.proto
}
fn read_handle<B>(mut buf: B) -> Result<Option<Handle>, Error>
where
B: Buf,
{
while buf.has_remaining() {
let (header, mut data) = read_attribute(&mut buf)?;
if header.ty == NFTA_CHAIN_HANDLE
&& let Ok(handle) = data.try_get_u64()
{
return Ok(Some(Handle::from_bits(handle)));
}
}
Ok(None)
}
}
impl Encode for AddChain<'_> {
fn encode<B>(&self, mut buf: B)
where
B: BufMut,
{
write_attribute(&mut buf, NFTA_CHAIN_TABLE, self.table.to_bytes_with_nul());
write_attribute(&mut buf, NFTA_CHAIN_NAME, self.name.to_bytes_with_nul());
if let Some(hook) = self.hook {
write_attribute(
&mut buf,
NFTA_CHAIN_POLICY,
&(hook.policy as u32).to_be_bytes(),
);
let mut nest = Vec::new();
write_attribute(
&mut nest,
NFTA_HOOK_HOOKNUM,
&(hook.hook as u32).to_be_bytes(),
);
write_attribute(&mut nest, NFTA_HOOK_PRIORITY, &hook.priority.to_be_bytes());
write_attribute(&mut buf, NFTA_CHAIN_HOOK | NLA_F_NESTED, &nest);
}
}
}
impl<'a> From<AddChain<'a>> for Command<'a> {
#[inline]
fn from(value: AddChain<'a>) -> Self {
Command::AddChain(value)
}
}
#[derive(Clone, Debug)]
pub struct DelChain<'a> {
pub table: Cow<'a, CStr>,
pub proto: ProtoFamily,
pub chain: ChainRef<'a>,
}
impl Message for DelChain<'_> {
const ID: u16 = NFT_MSG_DELCHAIN as u16;
fn proto(&self) -> ProtoFamily {
self.proto
}
}
impl Encode for DelChain<'_> {
fn encode<B>(&self, mut buf: B)
where
B: BufMut,
{
write_attribute(&mut buf, NFTA_CHAIN_TABLE, self.table.to_bytes_with_nul());
match &self.chain {
ChainRef::Name(name) => {
write_attribute(&mut buf, NFTA_CHAIN_NAME, name.to_bytes_with_nul());
}
ChainRef::Handle(handle) => {
write_attribute(&mut buf, NFTA_CHAIN_HANDLE, &handle.to_bits().to_be_bytes());
}
}
}
}
impl<'a> From<DelChain<'a>> for Command<'a> {
#[inline]
fn from(value: DelChain<'a>) -> Self {
Command::DelChain(value)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ChainRef<'a> {
Name(Cow<'a, CStr>),
Handle(Handle),
}
#[derive(Clone, Debug)]
pub struct AddRule<'a> {
pub table: Cow<'a, CStr>,
pub proto: ProtoFamily,
pub chain: Cow<'a, CStr>,
pub position: Option<u64>,
pub exprs: Vec<Expr>,
}
impl Message for AddRule<'_> {
const ID: u16 = NFT_MSG_NEWRULE as u16;
fn proto(&self) -> ProtoFamily {
self.proto
}
fn read_handle<B>(mut buf: B) -> Result<Option<Handle>, Error>
where
B: Buf,
{
while buf.has_remaining() {
let (header, mut data) = read_attribute(&mut buf)?;
if header.ty == NFTA_RULE_HANDLE
&& let Ok(handle) = data.try_get_u64()
{
return Ok(Some(Handle::from_bits(handle)));
}
}
Ok(None)
}
}
impl Encode for AddRule<'_> {
fn encode<B>(&self, mut buf: B)
where
B: BufMut,
{
write_attribute(&mut buf, NFTA_RULE_TABLE, self.table.to_bytes_with_nul());
write_attribute(&mut buf, NFTA_RULE_CHAIN, self.chain.to_bytes_with_nul());
if let Some(position) = self.position {
write_attribute(&mut buf, NFTA_RULE_POSITION, &position.to_be_bytes());
}
let mut exprs = Vec::new();
for expr in &self.exprs {
let mut data = Vec::new();
expr.encode(&mut data);
write_attribute(&mut exprs, NFTA_LIST_ELEM | NLA_F_NESTED, &data);
}
if !exprs.is_empty() {
write_attribute(&mut buf, NFTA_RULE_EXPRESSIONS | NLA_F_NESTED, &exprs);
}
}
}
impl<'a> From<AddRule<'a>> for Command<'a> {
#[inline]
fn from(value: AddRule<'a>) -> Self {
Command::AddRule(value)
}
}
#[derive(Clone, Debug)]
pub struct DelRule<'a> {
pub table: Cow<'a, CStr>,
pub proto: ProtoFamily,
pub chain: Cow<'a, CStr>,
pub handle: Handle,
}
impl Message for DelRule<'_> {
const ID: u16 = NFT_MSG_DELRULE as u16;
fn proto(&self) -> ProtoFamily {
self.proto
}
}
impl Encode for DelRule<'_> {
fn encode<B>(&self, mut buf: B)
where
B: BufMut,
{
write_attribute(&mut buf, NFTA_RULE_TABLE, self.table.to_bytes_with_nul());
write_attribute(&mut buf, NFTA_RULE_CHAIN, self.chain.to_bytes_with_nul());
write_attribute(
&mut buf,
NFTA_RULE_HANDLE,
&self.handle.to_bits().to_be_bytes(),
);
}
}
impl<'a> From<DelRule<'a>> for Command<'a> {
#[inline]
fn from(value: DelRule<'a>) -> Self {
Command::DelRule(value)
}
}