diff options
author | Simon THOBY <git@nightmared.fr> | 2022-11-15 22:25:36 +0100 |
---|---|---|
committer | Simon THOBY <git@nightmared.fr> | 2022-11-15 22:25:36 +0100 |
commit | d1170d81c85254d2fe5ef5d3fc92cc6eb35357a4 (patch) | |
tree | 6f5645e3b7313681f083135a3718a8da129574f3 /src/expr | |
parent | 22edb0197854bf4f504e833e69b0e545d382f065 (diff) |
exprs: implement bitwise and add support for unknown expressions
Diffstat (limited to 'src/expr')
-rw-r--r-- | src/expr/bitwise.rs | 127 | ||||
-rw-r--r-- | src/expr/cmp.rs | 25 | ||||
-rw-r--r-- | src/expr/immediate.rs | 30 | ||||
-rw-r--r-- | src/expr/mod.rs | 121 | ||||
-rw-r--r-- | src/expr/reject.rs | 5 | ||||
-rw-r--r-- | src/expr/verdict.rs | 12 |
6 files changed, 145 insertions, 175 deletions
diff --git a/src/expr/bitwise.rs b/src/expr/bitwise.rs index d34d22c..38c0383 100644 --- a/src/expr/bitwise.rs +++ b/src/expr/bitwise.rs @@ -1,69 +1,74 @@ -use super::{Expression, Rule, ToSlice}; -use crate::sys::{self, libc}; -use std::ffi::c_void; -use std::os::raw::c_char; +use super::{Expression, ExpressionData, Register}; +use crate::create_expr_type; +use crate::parser::DecodeError; +use crate::sys; -/// Expression for performing bitwise masking and XOR on the data in a register. -pub struct Bitwise<M: ToSlice, X: ToSlice> { - mask: M, - xor: X, -} +create_expr_type!( + inline with_builder : Bitwise, + [ + ( + get_dreg, + set_dreg, + with_dreg, + sys::NFTA_BITWISE_DREG, + Register, + Register + ), + ( + get_sreg, + set_sreg, + with_sreg, + sys::NFTA_BITWISE_SREG, + Register, + Register + ), + ( + get_len, + set_len, + with_len, + sys::NFTA_BITWISE_LEN, + U32, + u32 + ), + ( + get_mask, + set_mask, + with_mask, + sys::NFTA_BITWISE_MASK, + ExprData, + ExpressionData + ), + ( + get_xor, + set_xor, + with_xor, + sys::NFTA_BITWISE_XOR, + ExprData, + ExpressionData + ) + ] +); -impl<M: ToSlice, X: ToSlice> Bitwise<M, X> { - /// Returns a new `Bitwise` instance that first masks the value it's applied to with `mask` and - /// then performs xor with the value in `xor`. - pub fn new(mask: M, xor: X) -> Self { - Self { mask, xor } +impl Expression for Bitwise { + fn get_name() -> &'static str { + "bitwise" } } -impl<M: ToSlice, X: ToSlice> Expression for Bitwise<M, X> { - fn get_raw_name() -> *const c_char { - b"bitwise\0" as *const _ as *const c_char - } - - fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { - unsafe { - let expr = try_alloc!(sys::nftnl_expr_alloc(Self::get_raw_name())); - - let mask = self.mask.to_slice(); - let xor = self.xor.to_slice(); - assert!(mask.len() == xor.len()); - let len = mask.len() as u32; - - sys::nftnl_expr_set_u32( - expr, - sys::NFTNL_EXPR_BITWISE_SREG as u16, - libc::NFT_REG_1 as u32, - ); - sys::nftnl_expr_set_u32( - expr, - sys::NFTNL_EXPR_BITWISE_DREG as u16, - libc::NFT_REG_1 as u32, - ); - sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_BITWISE_LEN as u16, len); - - sys::nftnl_expr_set( - expr, - sys::NFTNL_EXPR_BITWISE_MASK as u16, - mask.as_ref() as *const _ as *const c_void, - len, - ); - sys::nftnl_expr_set( - expr, - sys::NFTNL_EXPR_BITWISE_XOR as u16, - xor.as_ref() as *const _ as *const c_void, - len, - ); - - expr +impl Bitwise { + /// Returns a new `Bitwise` instance that first masks the value it's applied to with `mask` and + /// then performs xor with the value in `xor` + pub fn new(mask: impl Into<Vec<u8>>, xor: impl Into<Vec<u8>>) -> Result<Self, DecodeError> { + let mask = mask.into(); + let xor = xor.into(); + if mask.len() != xor.len() { + return Err(DecodeError::IncompatibleLength); } + Ok(Self::builder() + .with_sreg(Register::Reg1) + .with_dreg(Register::Reg1) + .with_len(mask.len() as u32) + .with_xor(ExpressionData::builder().with_value(xor)) + .with_mask(ExpressionData::builder().with_value(mask))) } } - -#[macro_export] -macro_rules! nft_expr_bitwise { - (mask $mask:expr,xor $xor:expr) => { - $crate::expr::Bitwise::new($mask, $xor) - }; -} diff --git a/src/expr/cmp.rs b/src/expr/cmp.rs index f6ea900..d8f825f 100644 --- a/src/expr/cmp.rs +++ b/src/expr/cmp.rs @@ -157,31 +157,6 @@ impl<const N: usize> Expression for Cmp<[u8; N]> { } } -#[macro_export(local_inner_macros)] -macro_rules! nft_expr_cmp { - (@cmp_op ==) => { - $crate::expr::CmpOp::Eq - }; - (@cmp_op !=) => { - $crate::expr::CmpOp::Neq - }; - (@cmp_op <) => { - $crate::expr::CmpOp::Lt - }; - (@cmp_op <=) => { - $crate::expr::CmpOp::Lte - }; - (@cmp_op >) => { - $crate::expr::CmpOp::Gt - }; - (@cmp_op >=) => { - $crate::expr::CmpOp::Gte - }; - ($op:tt $data:expr) => { - $crate::expr::Cmp::new(nft_expr_cmp!(@cmp_op $op), $data) - }; -} - /// Can be used to compare the value loaded by [`Meta::IifName`] and [`Meta::OifName`]. Please note /// that it is faster to check interface index than name. /// diff --git a/src/expr/immediate.rs b/src/expr/immediate.rs index e9f7b5b..6f26bc3 100644 --- a/src/expr/immediate.rs +++ b/src/expr/immediate.rs @@ -1,29 +1,7 @@ -use super::{Expression, Register, VerdictAttribute}; +use super::{Expression, ExpressionData, Register}; use crate::{create_expr_type, sys}; create_expr_type!( - nested with_builder : ImmediateData, - [ - ( - get_value, - set_value, - with_value, - sys::NFTA_DATA_VALUE, - VecU8, - Vec<u8> - ), - ( - get_verdict, - set_verdict, - with_verdict, - sys::NFTA_DATA_VERDICT, - ExprVerdictAttribute, - VerdictAttribute - ) - ] -); - -create_expr_type!( inline with_builder : Immediate, [ ( @@ -39,8 +17,8 @@ create_expr_type!( set_data, with_data, sys::NFTA_IMMEDIATE_DATA, - ExprImmediateData, - ImmediateData + ExprData, + ExpressionData ) ] ); @@ -49,7 +27,7 @@ impl Immediate { pub fn new_data(data: Vec<u8>, register: Register) -> Self { Immediate::builder() .with_dreg(register) - .with_data(ImmediateData::builder().with_value(data)) + .with_data(ExpressionData::builder().with_value(data)) } } diff --git a/src/expr/mod.rs b/src/expr/mod.rs index 4c702b2..78b1717 100644 --- a/src/expr/mod.rs +++ b/src/expr/mod.rs @@ -26,10 +26,10 @@ use crate::sys::{self, nlattr}; use libc::NLA_TYPE_MASK; use thiserror::Error; -/* mod bitwise; pub use self::bitwise::*; +/* mod cmp; pub use self::cmp::*; @@ -295,7 +295,10 @@ macro_rules! create_expr_variant { Ok(AttributeType::ExpressionVariant(ExpressionVariant::from(res))) }, )+ - AttributeType::String(name) => Err(DecodeError::UnknownExpressionName(name.to_string())), + AttributeType::String(name) => { + info!("Unrecognized expression '{}', generating an ExpressionRaw", name); + ExpressionRaw::deserialize(buf).map(|(res, _)| AttributeType::ExpressionVariant(ExpressionVariant::ExpressionRaw(res))) + }, _ => unreachable!() } }, @@ -306,7 +309,13 @@ macro_rules! create_expr_variant { }; } -create_expr_variant!(ExpressionVariant, [Log, Log], [Immediate, Immediate]); +create_expr_variant!( + ExpressionVariant, + [Log, Log], + [Immediate, Immediate], + [Bitwise, Bitwise], + [ExpressionRaw, ExpressionRaw] +); #[derive(Debug, Clone, PartialEq, Eq)] pub struct ExpressionList { @@ -318,6 +327,11 @@ impl ExpressionList { Self { exprs: Vec::new() } } + /// Useful to add raw expressions because ExpressionHolder cannot infer alone its type + pub fn add_raw_expression(&mut self, e: ExpressionHolder) { + self.exprs.push(AttributeType::Expression(e)); + } + pub fn add_expression<T>(&mut self, e: T) where T: Expression, @@ -397,57 +411,52 @@ impl NfNetlinkDeserializable for ExpressionList { } } -#[macro_export(local_inner_macros)] -macro_rules! nft_expr { - (bitwise mask $mask:expr,xor $xor:expr) => { - nft_expr_bitwise!(mask $mask, xor $xor) - }; - (cmp $op:tt $data:expr) => { - nft_expr_cmp!($op $data) - }; - (counter) => { - $crate::expr::Counter { nb_bytes: 0, nb_packets: 0} - }; - (ct $key:ident set) => { - nft_expr_ct!($key set) - }; - (ct $key:ident) => { - nft_expr_ct!($key) - }; - (immediate $expr:ident $value:expr) => { - nft_expr_immediate!($expr $value) - }; - (log group $group:ident prefix $prefix:expr) => { - nft_expr_log!(group $group prefix $prefix) - }; - (log group $group:ident) => { - nft_expr_log!(group $group) - }; - (log prefix $prefix:expr) => { - nft_expr_log!(prefix $prefix) - }; - (log) => { - nft_expr_log!() - }; - (lookup $set:expr) => { - nft_expr_lookup!($set) - }; - (masquerade) => { - $crate::expr::Masquerade - }; - (meta $expr:ident set) => { - nft_expr_meta!($expr set) - }; - (meta $expr:ident) => { - nft_expr_meta!($expr) - }; - (payload $proto:ident $field:ident) => { - nft_expr_payload!($proto $field) - }; - (verdict $verdict:ident) => { - nft_expr_verdict!($verdict) - }; - (verdict $verdict:ident $chain:expr) => { - nft_expr_verdict!($verdict $chain) - }; +create_expr_type!( + nested with_builder : ExpressionData, + [ + ( + get_value, + set_value, + with_value, + sys::NFTA_DATA_VALUE, + VecU8, + Vec<u8> + ), + ( + get_verdict, + set_verdict, + with_verdict, + sys::NFTA_DATA_VERDICT, + ExprVerdictAttribute, + VerdictAttribute + ) + ] +); + +// default type for expressions that we do not handle yet +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ExpressionRaw(Vec<u8>); + +impl NfNetlinkAttribute for ExpressionRaw { + fn get_size(&self) -> usize { + self.0.get_size() + } + + unsafe fn write_payload(&self, addr: *mut u8) { + self.0.write_payload(addr); + } +} + +impl NfNetlinkDeserializable for ExpressionRaw { + fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + Ok((ExpressionRaw(buf.to_vec()), &[])) + } +} + +// Because we loose the name of the expression when parsing, this is the only expression +// where deserializing a message and the reserializing it alter its content +impl Expression for ExpressionRaw { + fn get_name() -> &'static str { + "unknown_expression" + } } diff --git a/src/expr/reject.rs b/src/expr/reject.rs index 19752ce..34fbee5 100644 --- a/src/expr/reject.rs +++ b/src/expr/reject.rs @@ -1,6 +1,9 @@ use super::{DeserializationError, Expression, Rule}; +use crate::sys::{ + self, + libc::{self, c_char}, +}; use crate::ProtoFamily; -use crate::sys::{self, libc::{self, c_char}}; /// A reject expression that defines the type of rejection message sent when discarding a packet. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] diff --git a/src/expr/verdict.rs b/src/expr/verdict.rs index 326ef3b..7c27af6 100644 --- a/src/expr/verdict.rs +++ b/src/expr/verdict.rs @@ -2,12 +2,12 @@ use std::fmt::Debug; use libc::{NF_ACCEPT, NF_DROP, NF_QUEUE}; -use super::{Expression, Immediate, ImmediateData, Register, Rule}; +use super::{ExpressionData, Immediate, Register}; use crate::{ - create_expr_type, impl_attr_getters_and_setters, - nlmsg::{NfNetlinkAttribute, NfNetlinkAttributes, NfNetlinkDeserializable}, - parser::{DecodeError, InnerFormat}, - sys::{self, NFT_BREAK, NFT_CONTINUE, NFT_GOTO, NFT_JUMP, NFT_REG_VERDICT, NFT_RETURN}, + create_expr_type, + nlmsg::{NfNetlinkAttribute, NfNetlinkDeserializable}, + parser::DecodeError, + sys::{self, NFT_BREAK, NFT_CONTINUE, NFT_GOTO, NFT_JUMP, NFT_RETURN}, }; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] @@ -119,6 +119,6 @@ impl Immediate { } Immediate::builder() .with_dreg(Register::Verdict) - .with_data(ImmediateData::builder().with_verdict(data)) + .with_data(ExpressionData::builder().with_verdict(data)) } } |