diff options
Diffstat (limited to 'src/expr')
-rw-r--r-- | src/expr/bitwise.rs | 17 | ||||
-rw-r--r-- | src/expr/cmp.rs | 18 | ||||
-rw-r--r-- | src/expr/immediate.rs | 31 | ||||
-rw-r--r-- | src/expr/lookup.rs | 94 | ||||
-rw-r--r-- | src/expr/meta.rs | 6 | ||||
-rw-r--r-- | src/expr/mod.rs | 165 | ||||
-rw-r--r-- | src/expr/payload.rs | 2 | ||||
-rw-r--r-- | src/expr/verdict.rs | 25 |
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)) - } -} |