aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--src/parser.rs13
-rw-r--r--tests/expr.rs117
8 files changed, 212 insertions, 238 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))
}
}
diff --git a/src/parser.rs b/src/parser.rs
index 42bcb00..8b14d74 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -36,6 +36,9 @@ pub enum DecodeError {
#[error("Missing information in the chain to create a rule")]
MissingChainInformationError,
+ #[error("The length of the arguments are not compatible with each other")]
+ IncompatibleLength,
+
#[error("Invalid subsystem, expected NFTABLES")]
InvalidSubsystem(u8),
@@ -72,9 +75,6 @@ pub enum DecodeError {
#[error("The object does not contain a name for the expression being parsed")]
MissingExpressionName,
- #[error("The expression name was not recognized")]
- UnknownExpressionName(String),
-
#[error("Unsupported attribute type")]
UnsupportedAttributeType(u16),
@@ -486,11 +486,12 @@ impl_attribute_holder!(
[ExpressionVariant, crate::expr::ExpressionVariant],
[ExpressionList, crate::expr::ExpressionList],
[ExprLog, crate::expr::Log],
- [ExprImmediate, crate::expr::ImmediateData],
- [ExprImmediateData, crate::expr::ImmediateData],
+ [ExprImmediate, crate::expr::Immediate],
+ [ExprData, crate::expr::ExpressionData],
[ExprVerdictAttribute, crate::expr::VerdictAttribute],
[ExprVerdictType, crate::expr::VerdictType],
- [Register, crate::expr::Register]
+ [Register, crate::expr::Register],
+ [ExprRaw, crate::expr::ExpressionRaw]
);
#[macro_export]
diff --git a/tests/expr.rs b/tests/expr.rs
index 1a7b6f7..46b50f0 100644
--- a/tests/expr.rs
+++ b/tests/expr.rs
@@ -1,4 +1,4 @@
-use rustables::expr::{ExpressionList, Immediate, Register, VerdictKind};
+use rustables::expr::{Bitwise, ExpressionList, Immediate, Register, VerdictKind};
//use rustables::expr::{
// Bitwise, Cmp, CmpOp, Conntrack, Counter, Expression, HeaderField, IcmpCode, Immediate, Log,
// LogGroup, LogPrefix, Lookup, Meta, Nat, NatType, Payload, Register, Reject, TcpHeaderField,
@@ -9,8 +9,8 @@ use rustables::expr::{ExpressionList, Immediate, Register, VerdictKind};
//use rustables::sys::libc::{nlmsghdr, NF_DROP};
//use rustables::{ProtoFamily, Rule};
//use std::ffi::CStr;
-//use std::net::Ipv4Addr;
-//
+use std::net::Ipv4Addr;
+
mod sys;
use libc::NF_DROP;
use sys::*;
@@ -18,60 +18,63 @@ use sys::*;
mod lib;
use lib::*;
-//#[test]
-//fn bitwise_expr_is_valid() {
-// let netmask = Ipv4Addr::new(255, 255, 255, 0);
-// let bitwise = Bitwise::new(netmask, 0);
-// let mut rule = get_test_rule();
-// let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &bitwise);
-// assert_eq!(nlmsghdr.nlmsg_len, 124);
-//
-// assert_eq!(
-// raw_expr,
-// NetlinkExpr::List(vec![
-// NetlinkExpr::Final(NFTA_RULE_TABLE, TABLE_NAME.to_vec()),
-// NetlinkExpr::Final(NFTA_RULE_CHAIN, CHAIN_NAME.to_vec()),
-// NetlinkExpr::Nested(
-// NFTA_RULE_EXPRESSIONS,
-// vec![NetlinkExpr::Nested(
-// NFTA_LIST_ELEM,
-// vec![
-// NetlinkExpr::Final(NFTA_EXPR_NAME, b"bitwise\0".to_vec()),
-// NetlinkExpr::Nested(
-// NFTA_EXPR_DATA,
-// vec![
-// NetlinkExpr::Final(
-// NFTA_BITWISE_SREG,
-// NFT_REG_1.to_be_bytes().to_vec()
-// ),
-// NetlinkExpr::Final(
-// NFTA_BITWISE_DREG,
-// NFT_REG_1.to_be_bytes().to_vec()
-// ),
-// NetlinkExpr::Final(NFTA_BITWISE_LEN, 4u32.to_be_bytes().to_vec()),
-// NetlinkExpr::Nested(
-// NFTA_BITWISE_MASK,
-// vec![NetlinkExpr::Final(
-// NFTA_DATA_VALUE,
-// vec![255, 255, 255, 0]
-// )]
-// ),
-// NetlinkExpr::Nested(
-// NFTA_BITWISE_XOR,
-// vec![NetlinkExpr::Final(
-// NFTA_DATA_VALUE,
-// 0u32.to_be_bytes().to_vec()
-// )]
-// )
-// ]
-// )
-// ]
-// )]
-// )
-// ])
-// .to_raw()
-// );
-//}
+#[test]
+fn bitwise_expr_is_valid() {
+ let netmask = Ipv4Addr::new(255, 255, 255, 0);
+ let bitwise = Bitwise::new(netmask.octets(), [0, 0, 0, 0]).unwrap();
+ let mut rule =
+ get_test_rule().with_expressions(ExpressionList::builder().with_expression(bitwise));
+
+ let mut buf = Vec::new();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg(&mut buf, &mut rule);
+ assert_eq!(nlmsghdr.nlmsg_len, 124);
+
+ assert_eq!(
+ raw_expr,
+ NetlinkExpr::List(vec![
+ NetlinkExpr::Final(NFTA_RULE_TABLE, TABLE_NAME.as_bytes().to_vec()),
+ NetlinkExpr::Final(NFTA_RULE_CHAIN, CHAIN_NAME.as_bytes().to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_RULE_EXPRESSIONS,
+ vec![NetlinkExpr::Nested(
+ NFTA_LIST_ELEM,
+ vec![
+ NetlinkExpr::Final(NFTA_EXPR_NAME, b"bitwise".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_BITWISE_SREG,
+ NFT_REG_1.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_BITWISE_DREG,
+ NFT_REG_1.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(NFTA_BITWISE_LEN, 4u32.to_be_bytes().to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_BITWISE_MASK,
+ vec![NetlinkExpr::Final(
+ NFTA_DATA_VALUE,
+ vec![255, 255, 255, 0]
+ )]
+ ),
+ NetlinkExpr::Nested(
+ NFTA_BITWISE_XOR,
+ vec![NetlinkExpr::Final(
+ NFTA_DATA_VALUE,
+ 0u32.to_be_bytes().to_vec()
+ )]
+ )
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
//
//#[test]
//fn cmp_expr_is_valid() {