aboutsummaryrefslogtreecommitdiff
path: root/src/expr
diff options
context:
space:
mode:
authorSimon THOBY <git@nightmared.fr>2022-11-15 22:25:36 +0100
committerSimon THOBY <git@nightmared.fr>2022-11-15 22:25:36 +0100
commitd1170d81c85254d2fe5ef5d3fc92cc6eb35357a4 (patch)
tree6f5645e3b7313681f083135a3718a8da129574f3 /src/expr
parent22edb0197854bf4f504e833e69b0e545d382f065 (diff)
exprs: implement bitwise and add support for unknown expressions
Diffstat (limited to 'src/expr')
-rw-r--r--src/expr/bitwise.rs127
-rw-r--r--src/expr/cmp.rs25
-rw-r--r--src/expr/immediate.rs30
-rw-r--r--src/expr/mod.rs121
-rw-r--r--src/expr/reject.rs5
-rw-r--r--src/expr/verdict.rs12
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))
}
}