aboutsummaryrefslogtreecommitdiff
path: root/src/expr
diff options
context:
space:
mode:
Diffstat (limited to 'src/expr')
-rw-r--r--src/expr/bitwise.rs17
-rw-r--r--src/expr/cmp.rs18
-rw-r--r--src/expr/immediate.rs31
-rw-r--r--src/expr/lookup.rs94
-rw-r--r--src/expr/meta.rs6
-rw-r--r--src/expr/mod.rs165
-rw-r--r--src/expr/payload.rs2
-rw-r--r--src/expr/verdict.rs25
8 files changed, 109 insertions, 249 deletions
diff --git a/src/expr/bitwise.rs b/src/expr/bitwise.rs
index 29d2d63..fb40a04 100644
--- a/src/expr/bitwise.rs
+++ b/src/expr/bitwise.rs
@@ -1,7 +1,8 @@
use rustables_macros::nfnetlink_struct;
-use super::{Expression, ExpressionData, Register};
-use crate::parser::DecodeError;
+use super::{Expression, Register};
+use crate::error::BuilderError;
+use crate::parser_impls::NfNetlinkData;
use crate::sys::{
NFTA_BITWISE_DREG, NFTA_BITWISE_LEN, NFTA_BITWISE_MASK, NFTA_BITWISE_SREG, NFTA_BITWISE_XOR,
};
@@ -16,9 +17,9 @@ pub struct Bitwise {
#[field(NFTA_BITWISE_LEN)]
len: u32,
#[field(NFTA_BITWISE_MASK)]
- mask: ExpressionData,
+ mask: NfNetlinkData,
#[field(NFTA_BITWISE_XOR)]
- xor: ExpressionData,
+ xor: NfNetlinkData,
}
impl Expression for Bitwise {
@@ -30,17 +31,17 @@ impl Expression for Bitwise {
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> {
+ pub fn new(mask: impl Into<Vec<u8>>, xor: impl Into<Vec<u8>>) -> Result<Self, BuilderError> {
let mask = mask.into();
let xor = xor.into();
if mask.len() != xor.len() {
- return Err(DecodeError::IncompatibleLength);
+ return Err(BuilderError::IncompatibleLength);
}
Ok(Bitwise::default()
.with_sreg(Register::Reg1)
.with_dreg(Register::Reg1)
.with_len(mask.len() as u32)
- .with_xor(ExpressionData::default().with_value(xor))
- .with_mask(ExpressionData::default().with_value(mask)))
+ .with_xor(NfNetlinkData::default().with_value(xor))
+ .with_mask(NfNetlinkData::default().with_value(mask)))
}
}
diff --git a/src/expr/cmp.rs b/src/expr/cmp.rs
index d69f73c..223902f 100644
--- a/src/expr/cmp.rs
+++ b/src/expr/cmp.rs
@@ -1,11 +1,15 @@
use rustables_macros::{nfnetlink_enum, nfnetlink_struct};
-use crate::sys::{
- NFTA_CMP_DATA, NFTA_CMP_OP, NFTA_CMP_SREG, NFT_CMP_EQ, NFT_CMP_GT, NFT_CMP_GTE, NFT_CMP_LT,
- NFT_CMP_LTE, NFT_CMP_NEQ,
+use crate::{
+ data_type::DataType,
+ parser_impls::NfNetlinkData,
+ sys::{
+ NFTA_CMP_DATA, NFTA_CMP_OP, NFTA_CMP_SREG, NFT_CMP_EQ, NFT_CMP_GT, NFT_CMP_GTE, NFT_CMP_LT,
+ NFT_CMP_LTE, NFT_CMP_NEQ,
+ },
};
-use super::{Expression, ExpressionData, Register};
+use super::{Expression, Register};
/// Comparison operator.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
@@ -34,17 +38,17 @@ pub struct Cmp {
#[field(NFTA_CMP_OP)]
op: CmpOp,
#[field(NFTA_CMP_DATA)]
- data: ExpressionData,
+ data: NfNetlinkData,
}
impl Cmp {
/// Returns a new comparison expression comparing the value loaded in the register with the
/// data in `data` using the comparison operator `op`.
- pub fn new(op: CmpOp, data: impl Into<Vec<u8>>) -> Self {
+ pub fn new(op: CmpOp, data: impl DataType) -> Self {
Cmp {
sreg: Some(Register::Reg1),
op: Some(op),
- data: Some(ExpressionData::default().with_value(data)),
+ data: Some(NfNetlinkData::default().with_value(data.data())),
}
}
}
diff --git a/src/expr/immediate.rs b/src/expr/immediate.rs
index 134f7e1..2fd9bd5 100644
--- a/src/expr/immediate.rs
+++ b/src/expr/immediate.rs
@@ -1,7 +1,10 @@
use rustables_macros::nfnetlink_struct;
-use super::{Expression, ExpressionData, Register};
-use crate::sys::{NFTA_IMMEDIATE_DATA, NFTA_IMMEDIATE_DREG};
+use super::{Expression, Register, Verdict, VerdictKind, VerdictType};
+use crate::{
+ parser_impls::NfNetlinkData,
+ sys::{NFTA_IMMEDIATE_DATA, NFTA_IMMEDIATE_DREG},
+};
#[derive(Clone, PartialEq, Eq, Default, Debug)]
#[nfnetlink_struct]
@@ -9,14 +12,34 @@ pub struct Immediate {
#[field(NFTA_IMMEDIATE_DREG)]
dreg: Register,
#[field(NFTA_IMMEDIATE_DATA)]
- data: ExpressionData,
+ data: NfNetlinkData,
}
impl Immediate {
pub fn new_data(data: Vec<u8>, register: Register) -> Self {
Immediate::default()
.with_dreg(register)
- .with_data(ExpressionData::default().with_value(data))
+ .with_data(NfNetlinkData::default().with_value(data))
+ }
+
+ pub fn new_verdict(kind: VerdictKind) -> Self {
+ let code = match kind {
+ VerdictKind::Drop => VerdictType::Drop,
+ VerdictKind::Accept => VerdictType::Accept,
+ VerdictKind::Queue => VerdictType::Queue,
+ VerdictKind::Continue => VerdictType::Continue,
+ VerdictKind::Break => VerdictType::Break,
+ VerdictKind::Jump { .. } => VerdictType::Jump,
+ VerdictKind::Goto { .. } => VerdictType::Goto,
+ VerdictKind::Return => VerdictType::Return,
+ };
+ let mut data = Verdict::default().with_code(code);
+ if let VerdictKind::Jump { chain } | VerdictKind::Goto { chain } = kind {
+ data.set_chain(chain);
+ }
+ Immediate::default()
+ .with_dreg(Register::Verdict)
+ .with_data(NfNetlinkData::default().with_verdict(data))
}
}
diff --git a/src/expr/lookup.rs b/src/expr/lookup.rs
index a0cc021..2ef830e 100644
--- a/src/expr/lookup.rs
+++ b/src/expr/lookup.rs
@@ -1,78 +1,40 @@
-use super::{DeserializationError, Expression, Rule};
-use crate::set::Set;
-use crate::sys::{self, libc};
-use std::ffi::{CStr, CString};
-use std::os::raw::c_char;
+use rustables_macros::nfnetlink_struct;
-#[derive(Debug, PartialEq)]
+use super::{Expression, Register};
+use crate::error::BuilderError;
+use crate::sys::{NFTA_LOOKUP_DREG, NFTA_LOOKUP_SET, NFTA_LOOKUP_SET_ID, NFTA_LOOKUP_SREG};
+use crate::Set;
+
+#[derive(Clone, PartialEq, Eq, Default, Debug)]
+#[nfnetlink_struct]
pub struct Lookup {
- set_name: CString,
+ #[field(NFTA_LOOKUP_SET)]
+ set: String,
+ #[field(NFTA_LOOKUP_SREG)]
+ sreg: Register,
+ #[field(NFTA_LOOKUP_DREG)]
+ dreg: Register,
+ #[field(NFTA_LOOKUP_SET_ID)]
set_id: u32,
}
impl Lookup {
- /// Creates a new lookup entry. May return None if the set has no name.
- pub fn new<K>(set: &Set<K>) -> Option<Self> {
- set.get_name().map(|set_name| Lookup {
- set_name: set_name.to_owned(),
- set_id: set.get_id(),
- })
- }
-}
-
-impl Expression for Lookup {
- fn get_raw_name() -> *const libc::c_char {
- b"lookup\0" as *const _ as *const c_char
- }
-
- fn from_expr(expr: *const sys::nftnl_expr) -> Result<Self, DeserializationError>
- where
- Self: Sized,
- {
- unsafe {
- let set_name = sys::nftnl_expr_get_str(expr, sys::NFTNL_EXPR_LOOKUP_SET as u16);
- let set_id = sys::nftnl_expr_get_u32(expr, sys::NFTNL_EXPR_LOOKUP_SET_ID as u16);
-
- if set_name.is_null() {
- return Err(DeserializationError::NullPointer);
- }
-
- let set_name = CStr::from_ptr(set_name).to_owned();
-
- Ok(Lookup { set_id, set_name })
+ /// Creates a new lookup entry. May return BuilderError::MissingSetName if the set has no name.
+ pub fn new(set: &Set) -> Result<Self, BuilderError> {
+ let mut res = Lookup::default()
+ .with_set(set.get_name().ok_or(BuilderError::MissingSetName)?)
+ .with_sreg(Register::Reg1);
+
+ if let Some(id) = set.get_id() {
+ res.set_set_id(*id);
}
- }
-
- fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr {
- unsafe {
- let expr = try_alloc!(sys::nftnl_expr_alloc(Self::get_raw_name()));
-
- sys::nftnl_expr_set_u32(
- expr,
- sys::NFTNL_EXPR_LOOKUP_SREG as u16,
- libc::NFT_REG_1 as u32,
- );
- sys::nftnl_expr_set_str(
- expr,
- sys::NFTNL_EXPR_LOOKUP_SET as u16,
- self.set_name.as_ptr() as *const _ as *const c_char,
- );
- sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_LOOKUP_SET_ID as u16, self.set_id);
- // This code is left here since it's quite likely we need it again when we get further
- // if self.reverse {
- // sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_LOOKUP_FLAGS as u16,
- // libc::NFT_LOOKUP_F_INV as u32);
- // }
-
- expr
- }
+ Ok(res)
}
}
-#[macro_export]
-macro_rules! nft_expr_lookup {
- ($set:expr) => {
- $crate::expr::Lookup::new($set)
- };
+impl Expression for Lookup {
+ fn get_name() -> &'static str {
+ "lookup"
+ }
}
diff --git a/src/expr/meta.rs b/src/expr/meta.rs
index 79016bd..d0fecee 100644
--- a/src/expr/meta.rs
+++ b/src/expr/meta.rs
@@ -49,6 +49,12 @@ pub struct Meta {
sreg: Register,
}
+impl Meta {
+ pub fn new(ty: MetaType) -> Self {
+ Meta::default().with_dreg(Register::Reg1).with_key(ty)
+ }
+}
+
impl Expression for Meta {
fn get_name() -> &'static str {
"meta"
diff --git a/src/expr/mod.rs b/src/expr/mod.rs
index cfc01c8..979ebb2 100644
--- a/src/expr/mod.rs
+++ b/src/expr/mod.rs
@@ -4,21 +4,15 @@
//! [`Rule`]: struct.Rule.html
use std::fmt::Debug;
-use std::mem::transmute;
-
-use crate::nlmsg::NfNetlinkAttribute;
-use crate::nlmsg::NfNetlinkDeserializable;
-use crate::parser::pad_netlink_object;
-use crate::parser::pad_netlink_object_with_variable_size;
-use crate::parser::write_attribute;
-use crate::parser::DecodeError;
-use crate::sys::{self, nlattr};
-use crate::sys::{
- NFTA_DATA_VALUE, NFTA_DATA_VERDICT, NFTA_EXPR_DATA, NFTA_EXPR_NAME, NLA_TYPE_MASK,
-};
+
use rustables_macros::nfnetlink_struct;
use thiserror::Error;
+use crate::error::DecodeError;
+use crate::nlmsg::{NfNetlinkAttribute, NfNetlinkDeserializable};
+use crate::parser_impls::NfNetlinkList;
+use crate::sys::{self, NFTA_EXPR_DATA, NFTA_EXPR_NAME};
+
mod bitwise;
pub use self::bitwise::*;
@@ -36,11 +30,9 @@ pub use self::immediate::*;
mod log;
pub use self::log::*;
-/*
mod lookup;
pub use self::lookup::*;
-*/
mod masquerade;
pub use self::masquerade::*;
@@ -105,19 +97,18 @@ pub struct RawExpression {
data: ExpressionVariant,
}
-impl RawExpression {
- pub fn new<T>(expr: T) -> Self
- where
- T: Expression,
- ExpressionVariant: From<T>,
- {
+impl<T> From<T> for RawExpression
+where
+ T: Expression,
+ ExpressionVariant: From<T>,
+{
+ fn from(val: T) -> Self {
RawExpression::default()
.with_name(T::get_name())
- .with_data(ExpressionVariant::from(expr))
+ .with_data(ExpressionVariant::from(val))
}
}
-#[macro_export]
macro_rules! create_expr_variant {
($enum:ident $(, [$name:ident, $type:ty])+) => {
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -162,14 +153,14 @@ macro_rules! create_expr_variant {
&mut self,
attr_type: u16,
buf: &[u8],
- ) -> Result<(), $crate::parser::DecodeError> {
+ ) -> Result<(), $crate::error::DecodeError> {
debug!("Decoding attribute {} in an expression", attr_type);
match attr_type {
x if x == sys::NFTA_EXPR_NAME => {
debug!("Calling {}::deserialize()", std::any::type_name::<String>());
let (val, remaining) = String::deserialize(buf)?;
if remaining.len() != 0 {
- return Err($crate::parser::DecodeError::InvalidDataSize);
+ return Err($crate::error::DecodeError::InvalidDataSize);
}
self.name = Some(val);
Ok(())
@@ -178,14 +169,14 @@ macro_rules! create_expr_variant {
// we can assume we have already the name parsed, as that's how we identify the
// type of expression
let name = self.name.as_ref()
- .ok_or($crate::parser::DecodeError::MissingExpressionName)?;
+ .ok_or($crate::error::DecodeError::MissingExpressionName)?;
match name {
$(
x if x == <$type>::get_name() => {
debug!("Calling {}::deserialize()", std::any::type_name::<$type>());
let (res, remaining) = <$type>::deserialize(buf)?;
if remaining.len() != 0 {
- return Err($crate::parser::DecodeError::InvalidDataSize);
+ return Err($crate::error::DecodeError::InvalidDataSize);
}
self.data = Some(ExpressionVariant::from(res));
Ok(())
@@ -207,126 +198,22 @@ macro_rules! create_expr_variant {
create_expr_variant!(
ExpressionVariant,
- [Log, Log],
- [Immediate, Immediate],
[Bitwise, Bitwise],
+ [Cmp, Cmp],
+ [Conntrack, Conntrack],
+ [Counter, Counter],
[ExpressionRaw, ExpressionRaw],
+ [Immediate, Immediate],
+ [Log, Log],
+ [Lookup, Lookup],
+ [Masquerade, Masquerade],
[Meta, Meta],
- [Reject, Reject],
- [Counter, Counter],
[Nat, Nat],
[Payload, Payload],
- [Cmp, Cmp],
- [Conntrack, Conntrack],
- [Masquerade, Masquerade]
+ [Reject, Reject]
);
-#[derive(Debug, Clone, PartialEq, Eq, Default)]
-pub struct ExpressionList {
- exprs: Vec<RawExpression>,
-}
-
-impl ExpressionList {
- /// Useful to add raw expressions because RawExpression cannot infer alone its type
- pub fn add_raw_expression(&mut self, e: RawExpression) {
- self.exprs.push(e);
- }
-
- pub fn add_expression<T>(&mut self, e: T)
- where
- T: Expression,
- ExpressionVariant: From<T>,
- {
- self.exprs.push(RawExpression::new(e));
- }
-
- pub fn with_expression<T>(mut self, e: T) -> Self
- where
- T: Expression,
- ExpressionVariant: From<T>,
- {
- self.add_expression(e);
- self
- }
-
- pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a ExpressionVariant> {
- self.exprs.iter().map(|e| e.get_data().unwrap())
- }
-}
-
-impl NfNetlinkAttribute for ExpressionList {
- fn is_nested(&self) -> bool {
- true
- }
-
- fn get_size(&self) -> usize {
- // one nlattr LIST_ELEM per object
- self.exprs.iter().fold(0, |acc, item| {
- acc + item.get_size() + pad_netlink_object::<nlattr>()
- })
- }
-
- unsafe fn write_payload(&self, mut addr: *mut u8) {
- for item in &self.exprs {
- write_attribute(sys::NFTA_LIST_ELEM, item, addr);
- addr = addr.offset((pad_netlink_object::<nlattr>() + item.get_size()) as isize);
- }
- }
-}
-
-impl NfNetlinkDeserializable for ExpressionList {
- fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
- let mut exprs = Vec::new();
-
- let mut pos = 0;
- while buf.len() - pos > pad_netlink_object::<nlattr>() {
- let nlattr = unsafe { *transmute::<*const u8, *const nlattr>(buf[pos..].as_ptr()) };
- // ignore the byteorder and nested attributes
- let nla_type = nlattr.nla_type & NLA_TYPE_MASK as u16;
-
- if nla_type != sys::NFTA_LIST_ELEM {
- return Err(DecodeError::UnsupportedAttributeType(nla_type));
- }
-
- let (expr, remaining) = RawExpression::deserialize(
- &buf[pos + pad_netlink_object::<nlattr>()..pos + nlattr.nla_len as usize],
- )?;
- if remaining.len() != 0 {
- return Err(DecodeError::InvalidDataSize);
- }
- exprs.push(expr);
-
- pos += pad_netlink_object_with_variable_size(nlattr.nla_len as usize);
- }
-
- if pos != buf.len() {
- Err(DecodeError::InvalidDataSize)
- } else {
- Ok((Self { exprs }, &[]))
- }
- }
-}
-
-impl<T> From<Vec<T>> for ExpressionList
-where
- ExpressionVariant: From<T>,
- T: Expression,
-{
- fn from(v: Vec<T>) -> Self {
- ExpressionList {
- exprs: v.into_iter().map(RawExpression::new).collect(),
- }
- }
-}
-
-#[derive(Clone, PartialEq, Eq, Default, Debug)]
-#[nfnetlink_struct(nested = true)]
-pub struct ExpressionData {
- #[field(NFTA_DATA_VALUE)]
- value: Vec<u8>,
- #[field(NFTA_DATA_VERDICT)]
- verdict: VerdictAttribute,
-}
+pub type ExpressionList = NfNetlinkList<RawExpression>;
// default type for expressions that we do not handle yet
#[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/src/expr/payload.rs b/src/expr/payload.rs
index 490a4ec..d0b2cea 100644
--- a/src/expr/payload.rs
+++ b/src/expr/payload.rs
@@ -2,7 +2,7 @@ use rustables_macros::nfnetlink_struct;
use super::{Expression, Register};
use crate::{
- parser::DecodeError,
+ error::DecodeError,
sys::{self, NFT_PAYLOAD_LL_HEADER, NFT_PAYLOAD_NETWORK_HEADER, NFT_PAYLOAD_TRANSPORT_HEADER},
};
diff --git a/src/expr/verdict.rs b/src/expr/verdict.rs
index c4facfb..7edf7cd 100644
--- a/src/expr/verdict.rs
+++ b/src/expr/verdict.rs
@@ -3,7 +3,6 @@ use std::fmt::Debug;
use libc::{NF_ACCEPT, NF_DROP, NF_QUEUE};
use rustables_macros::{nfnetlink_enum, nfnetlink_struct};
-use super::{ExpressionData, Immediate, Register};
use crate::sys::{
NFTA_VERDICT_CHAIN, NFTA_VERDICT_CHAIN_ID, NFTA_VERDICT_CODE, NFT_BREAK, NFT_CONTINUE,
NFT_GOTO, NFT_JUMP, NFT_RETURN,
@@ -24,7 +23,7 @@ pub enum VerdictType {
#[derive(Clone, PartialEq, Eq, Default, Debug)]
#[nfnetlink_struct(nested = true)]
-pub struct VerdictAttribute {
+pub struct Verdict {
#[field(NFTA_VERDICT_CODE)]
code: VerdictType,
#[field(NFTA_VERDICT_CHAIN)]
@@ -50,25 +49,3 @@ pub enum VerdictKind {
},
Return,
}
-
-impl Immediate {
- pub fn new_verdict(kind: VerdictKind) -> Self {
- let code = match kind {
- VerdictKind::Drop => VerdictType::Drop,
- VerdictKind::Accept => VerdictType::Accept,
- VerdictKind::Queue => VerdictType::Queue,
- VerdictKind::Continue => VerdictType::Continue,
- VerdictKind::Break => VerdictType::Break,
- VerdictKind::Jump { .. } => VerdictType::Jump,
- VerdictKind::Goto { .. } => VerdictType::Goto,
- VerdictKind::Return => VerdictType::Return,
- };
- let mut data = VerdictAttribute::default().with_code(code);
- if let VerdictKind::Jump { chain } | VerdictKind::Goto { chain } = kind {
- data.set_chain(chain);
- }
- Immediate::default()
- .with_dreg(Register::Verdict)
- .with_data(ExpressionData::default().with_verdict(data))
- }
-}