aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chain.rs133
-rw-r--r--src/chain_methods.rs40
-rw-r--r--src/expr/bitwise.rs39
-rw-r--r--src/expr/immediate.rs14
-rw-r--r--src/expr/log.rs73
-rw-r--r--src/expr/meta.rs230
-rw-r--r--src/expr/mod.rs175
-rw-r--r--src/expr/verdict.rs18
-rw-r--r--src/lib.rs24
-rw-r--r--src/nlmsg.rs17
-rw-r--r--src/parser.rs366
-rw-r--r--src/query.rs15
-rw-r--r--src/rule.rs191
-rw-r--r--src/table.rs88
14 files changed, 539 insertions, 884 deletions
diff --git a/src/chain.rs b/src/chain.rs
index cce0fa9..eeedcd1 100644
--- a/src/chain.rs
+++ b/src/chain.rs
@@ -1,12 +1,12 @@
use libc::{NF_ACCEPT, NF_DROP};
-use crate::nlmsg::{
- NfNetlinkAttribute, NfNetlinkAttributes, NfNetlinkDeserializable, NfNetlinkObject,
- NfNetlinkWriter,
-};
-use crate::parser::{parse_object, DecodeError, InnerFormat, NfNetlinkAttributeReader};
+use crate::nlmsg::{NfNetlinkAttribute, NfNetlinkDeserializable, NfNetlinkObject, NfNetlinkWriter};
+use crate::parser::{DecodeError, InnerFormat, Parsable};
use crate::sys::{self, NFT_MSG_DELCHAIN, NFT_MSG_NEWCHAIN, NLM_F_ACK, NLM_F_CREATE};
-use crate::{impl_attr_getters_and_setters, MsgType, ProtocolFamily, Table};
+use crate::{
+ create_wrapper_type, impl_attr_getters_and_setters, impl_nfnetlinkattribute, MsgType,
+ ProtocolFamily, Table,
+};
use std::convert::TryFrom;
use std::fmt::Debug;
@@ -28,29 +28,8 @@ pub enum HookClass {
PostRouting = libc::NF_INET_POST_ROUTING,
}
-#[derive(Clone, PartialEq, Eq)]
-pub struct Hook {
- inner: NfNetlinkAttributes,
-}
-
-impl Hook {
- pub fn new(class: HookClass, priority: ChainPriority) -> Self {
- Hook {
- inner: NfNetlinkAttributes::new(),
- }
- .with_class(class as u32)
- .with_priority(priority as u32)
- }
-}
-
-impl Debug for Hook {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.inner_format_struct(f.debug_struct("Hook"))?.finish()
- }
-}
-
-impl_attr_getters_and_setters!(
- Hook,
+create_wrapper_type!(
+ nested: Hook,
[
// Define the action netfilter will apply to packets processed by this chain, but that did not match any rules in it.
(
@@ -58,7 +37,7 @@ impl_attr_getters_and_setters!(
set_class,
with_class,
sys::NFTA_HOOK_HOOKNUM,
- U32,
+ class,
u32
),
(
@@ -66,31 +45,17 @@ impl_attr_getters_and_setters!(
set_priority,
with_priority,
sys::NFTA_HOOK_PRIORITY,
- U32,
+ priority,
u32
)
]
);
-impl NfNetlinkAttribute for Hook {
- fn is_nested(&self) -> bool {
- true
- }
-
- fn get_size(&self) -> usize {
- self.inner.get_size()
- }
-
- unsafe fn write_payload(&self, addr: *mut u8) {
- self.inner.write_payload(addr)
- }
-}
-
-impl NfNetlinkDeserializable for Hook {
- fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
- let reader = NfNetlinkAttributeReader::new(buf, buf.len())?;
- let inner = reader.decode::<Self>()?;
- Ok((Hook { inner }, &[]))
+impl Hook {
+ pub fn new(class: HookClass, priority: ChainPriority) -> Self {
+ Hook::default()
+ .with_class(class as u32)
+ .with_priority(priority as u32)
}
}
@@ -186,10 +151,16 @@ impl NfNetlinkDeserializable for ChainType {
/// [`Table`]: struct.Table.html
/// [`Rule`]: struct.Rule.html
/// [`set_hook`]: #method.set_hook
-#[derive(PartialEq, Eq)]
+#[derive(PartialEq, Eq, Default)]
pub struct Chain {
family: ProtocolFamily,
- inner: NfNetlinkAttributes,
+ flags: Option<u32>,
+ name: Option<String>,
+ hook: Option<Hook>,
+ policy: Option<ChainPolicy>,
+ table: Option<String>,
+ chain_type: Option<ChainType>,
+ userdata: Option<Vec<u8>>,
}
impl Chain {
@@ -197,10 +168,8 @@ impl Chain {
///
/// [`Table`]: struct.Table.html
pub fn new(table: &Table) -> Chain {
- let mut chain = Chain {
- family: table.get_family(),
- inner: NfNetlinkAttributes::new(),
- };
+ let mut chain = Chain::default();
+ chain.family = table.family;
if let Some(table_name) = table.get_name() {
chain.set_table(table_name);
@@ -213,10 +182,6 @@ impl Chain {
self.family
}
- fn raw_attributes(&self) -> &NfNetlinkAttributes {
- &self.inner
- }
-
/*
/// Returns a textual description of the chain.
pub fn get_str(&self) -> CString {
@@ -268,31 +233,29 @@ impl NfNetlinkObject for Chain {
seq,
None,
);
- self.inner.serialize(writer);
+ let buf = writer.add_data_zeroed(self.get_size());
+ unsafe {
+ self.write_payload(buf.as_mut_ptr());
+ }
writer.finalize_writing_object();
}
}
impl NfNetlinkDeserializable for Chain {
fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
- let (inner, nfgenmsg, remaining_data) =
- parse_object::<Self>(buf, NFT_MSG_NEWCHAIN, NFT_MSG_DELCHAIN)?;
+ let (mut obj, nfgenmsg, remaining_data) =
+ Self::parse_object(buf, NFT_MSG_NEWCHAIN, NFT_MSG_DELCHAIN)?;
+ obj.family = ProtocolFamily::try_from(nfgenmsg.nfgen_family as i32)?;
- Ok((
- Self {
- inner,
- family: ProtocolFamily::try_from(nfgenmsg.nfgen_family as i32)?,
- },
- remaining_data,
- ))
+ Ok((obj, remaining_data))
}
}
impl_attr_getters_and_setters!(
Chain,
[
- (get_flags, set_flags, with_flags, sys::NFTA_CHAIN_FLAGS, U32, u32),
- (get_name, set_name, with_name, sys::NFTA_CHAIN_NAME, String, String),
+ (get_table, set_table, with_table, sys::NFTA_CHAIN_TABLE, table, String),
+ (get_name, set_name, with_name, sys::NFTA_CHAIN_NAME, name, String),
// Sets the hook and priority for this chain. Without calling this method the chain will
// become a "regular chain" without any hook and will thus not receive any traffic unless
// some rule forward packets to it via goto or jump verdicts.
@@ -300,22 +263,38 @@ impl_attr_getters_and_setters!(
// By calling `set_hook` with a hook the chain that is created will be registered with that
// hook and is thus a "base chain". A "base chain" is an entry point for packets from the
// networking stack.
- (get_hook, set_hook, with_hook, sys::NFTA_CHAIN_HOOK, ChainHook, Hook),
- (get_policy, set_policy, with_policy, sys::NFTA_CHAIN_POLICY, ChainPolicy, ChainPolicy),
- (get_table, set_table, with_table, sys::NFTA_CHAIN_TABLE, String, String),
+ (get_hook, set_hook, with_hook, sys::NFTA_CHAIN_HOOK, hook, Hook),
+ (get_policy, set_policy, with_policy, sys::NFTA_CHAIN_POLICY, policy, ChainPolicy),
// This only applies if the chain has been registered with a hook by calling `set_hook`.
- (get_type, set_type, with_type, sys::NFTA_CHAIN_TYPE, ChainType, ChainType),
+ (get_type, set_type, with_type, sys::NFTA_CHAIN_TYPE, chain_type, ChainType),
+ (get_flags, set_flags, with_flags, sys::NFTA_CHAIN_FLAGS, flags, u32),
(
get_userdata,
set_userdata,
with_userdata,
sys::NFTA_CHAIN_USERDATA,
- VecU8,
+ userdata,
Vec<u8>
)
]
);
+impl_nfnetlinkattribute!(
+ inline : Chain,
+ [
+ (sys::NFTA_CHAIN_TABLE, table),
+ (sys::NFTA_CHAIN_NAME, name),
+ (sys::NFTA_CHAIN_HOOK, hook),
+ (sys::NFTA_CHAIN_POLICY, policy),
+ (sys::NFTA_CHAIN_TYPE, chain_type),
+ (sys::NFTA_CHAIN_FLAGS, flags),
+ (
+ sys::NFTA_CHAIN_USERDATA,
+ userdata
+ )
+ ]
+);
+
pub fn list_chains_for_table(table: &Table) -> Result<Vec<Chain>, crate::query::Error> {
let mut result = Vec::new();
crate::query::list_objects_with_data(
diff --git a/src/chain_methods.rs b/src/chain_methods.rs
deleted file mode 100644
index d384c35..0000000
--- a/src/chain_methods.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use crate::{Batch, Chain, Hook, MsgType, Policy, Table};
-use std::ffi::CString;
-use std::rc::Rc;
-
-
-/// A helper trait over [`crate::Chain`].
-pub trait ChainMethods {
- /// Creates a new Chain instance from a [`crate::Hook`] over a [`crate::Table`].
- fn from_hook(hook: Hook, table: Rc<Table>) -> Self
- where Self: std::marker::Sized;
- /// Adds a [`crate::Policy`] to the current Chain.
- fn verdict(self, policy: Policy) -> Self;
- fn add_to_batch(self, batch: &mut Batch) -> Self;
-}
-
-
-impl ChainMethods for Chain {
- fn from_hook(hook: Hook, table: Rc<Table>) -> Self {
- let chain_name = match hook {
- Hook::PreRouting => "prerouting",
- Hook::Out => "out",
- Hook::PostRouting => "postrouting",
- Hook::Forward => "forward",
- Hook::In => "in",
- };
- let chain_name = CString::new(chain_name).unwrap();
- let mut chain = Chain::new(&chain_name, table);
- chain.set_hook(hook, 0);
- chain
- }
- fn verdict(mut self, policy: Policy) -> Self {
- self.set_policy(policy);
- self
- }
- fn add_to_batch(self, batch: &mut Batch) -> Self {
- batch.add(&self, MsgType::Add);
- self
- }
-}
-
diff --git a/src/expr/bitwise.rs b/src/expr/bitwise.rs
index 38c0383..73c2467 100644
--- a/src/expr/bitwise.rs
+++ b/src/expr/bitwise.rs
@@ -1,41 +1,34 @@
use super::{Expression, ExpressionData, Register};
-use crate::create_expr_type;
+use crate::create_wrapper_type;
use crate::parser::DecodeError;
use crate::sys;
-create_expr_type!(
- inline with_builder : Bitwise,
+create_wrapper_type!(
+ inline: Bitwise,
[
(
- get_dreg,
- set_dreg,
- with_dreg,
- sys::NFTA_BITWISE_DREG,
- Register,
- Register
- ),
- (
get_sreg,
set_sreg,
with_sreg,
sys::NFTA_BITWISE_SREG,
- Register,
+ sreg,
Register
),
(
- get_len,
- set_len,
- with_len,
- sys::NFTA_BITWISE_LEN,
- U32,
- u32
+ get_dreg,
+ set_dreg,
+ with_dreg,
+ sys::NFTA_BITWISE_DREG,
+ dreg,
+ Register
),
+ (get_len, set_len, with_len, sys::NFTA_BITWISE_LEN, len, u32),
(
get_mask,
set_mask,
with_mask,
sys::NFTA_BITWISE_MASK,
- ExprData,
+ mask,
ExpressionData
),
(
@@ -43,7 +36,7 @@ create_expr_type!(
set_xor,
with_xor,
sys::NFTA_BITWISE_XOR,
- ExprData,
+ xor,
ExpressionData
)
]
@@ -64,11 +57,11 @@ impl Bitwise {
if mask.len() != xor.len() {
return Err(DecodeError::IncompatibleLength);
}
- Ok(Self::builder()
+ Ok(Bitwise::default()
.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)))
+ .with_xor(ExpressionData::default().with_value(xor))
+ .with_mask(ExpressionData::default().with_value(mask)))
}
}
diff --git a/src/expr/immediate.rs b/src/expr/immediate.rs
index 6f26bc3..925ca06 100644
--- a/src/expr/immediate.rs
+++ b/src/expr/immediate.rs
@@ -1,15 +1,15 @@
use super::{Expression, ExpressionData, Register};
-use crate::{create_expr_type, sys};
+use crate::{create_wrapper_type, sys};
-create_expr_type!(
- inline with_builder : Immediate,
+create_wrapper_type!(
+ inline: Immediate,
[
(
get_dreg,
set_dreg,
with_dreg,
sys::NFTA_IMMEDIATE_DREG,
- Register,
+ dreg,
Register
),
(
@@ -17,7 +17,7 @@ create_expr_type!(
set_data,
with_data,
sys::NFTA_IMMEDIATE_DATA,
- ExprData,
+ data,
ExpressionData
)
]
@@ -25,9 +25,9 @@ create_expr_type!(
impl Immediate {
pub fn new_data(data: Vec<u8>, register: Register) -> Self {
- Immediate::builder()
+ Immediate::default()
.with_dreg(register)
- .with_data(ExpressionData::builder().with_value(data))
+ .with_data(ExpressionData::default().with_value(data))
}
}
diff --git a/src/expr/log.rs b/src/expr/log.rs
index cf50cb2..82c201d 100644
--- a/src/expr/log.rs
+++ b/src/expr/log.rs
@@ -1,18 +1,17 @@
use super::{Expression, ExpressionError};
-use crate::create_expr_type;
-use crate::nlmsg::NfNetlinkAttributes;
+use crate::create_wrapper_type;
use crate::sys;
// A Log expression will log all packets that match the rule.
-create_expr_type!(
- inline with_builder : Log,
+create_wrapper_type!(
+ inline: Log,
[
(
get_group,
set_group,
with_group,
sys::NFTA_LOG_GROUP,
- U32,
+ group,
u32
),
(
@@ -20,7 +19,7 @@ create_expr_type!(
set_prefix,
with_prefix,
sys::NFTA_LOG_PREFIX,
- String,
+ prefix,
String
)
]
@@ -31,11 +30,7 @@ impl Log {
group: Option<u16>,
prefix: Option<impl Into<String>>,
) -> Result<Log, ExpressionError> {
- let mut res = Log {
- inner: NfNetlinkAttributes::new(),
- //pub group: Option<LogGroup>,
- //pub prefix: Option<LogPrefix>,
- };
+ let mut res = Log::default();
if let Some(group) = group {
res.set_group(group);
}
@@ -55,60 +50,4 @@ impl Expression for Log {
fn get_name() -> &'static str {
"log"
}
- /*
- fn from_expr(expr: *const sys::nftnl_expr) -> Result<Self, DeserializationError>
- where
- Self: Sized,
- {
- unsafe {
- let mut group = None;
- if sys::nftnl_expr_is_set(expr, sys::NFTNL_EXPR_LOG_GROUP as u16) {
- group = Some(LogGroup(sys::nftnl_expr_get_u32(
- expr,
- sys::NFTNL_EXPR_LOG_GROUP as u16,
- ) as u16));
- }
- let mut prefix = None;
- if sys::nftnl_expr_is_set(expr, sys::NFTNL_EXPR_LOG_PREFIX as u16) {
- let raw_prefix = sys::nftnl_expr_get_str(expr, sys::NFTNL_EXPR_LOG_PREFIX as u16);
- if raw_prefix.is_null() {
- return Err(DeserializationError::NullPointer);
- } else {
- prefix = Some(LogPrefix(CStr::from_ptr(raw_prefix).to_owned()));
- }
- }
- Ok(Log { group, prefix })
- }
- }
-
- fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr {
- unsafe {
- let expr = try_alloc!(sys::nftnl_expr_alloc(b"log\0" as *const _ as *const c_char));
- if let Some(log_group) = self.group {
- sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_LOG_GROUP as u16, log_group.0 as u32);
- };
- if let Some(LogPrefix(prefix)) = &self.prefix {
- sys::nftnl_expr_set_str(expr, sys::NFTNL_EXPR_LOG_PREFIX as u16, prefix.as_ptr());
- };
-
- expr
- }
- }
- */
-}
-
-#[macro_export]
-macro_rules! nft_expr_log {
- (group $group:ident prefix $prefix:expr) => {
- $crate::expr::Log::new(Some($group), Some($prefix))
- };
- (prefix $prefix:expr) => {
- $crate::expr::Log::new(None, Some($prefix))
- };
- (group $group:ident) => {
- $crate::expr::Log::new(Some($group), None)
- };
- () => {
- $crate::expr::Log::new(None, None)
- };
}
diff --git a/src/expr/meta.rs b/src/expr/meta.rs
index a015f65..bb8023d 100644
--- a/src/expr/meta.rs
+++ b/src/expr/meta.rs
@@ -1,175 +1,115 @@
-use super::{DeserializationError, Expression, Rule};
-use crate::sys::{self, libc};
-use std::os::raw::c_char;
+use super::{Expression, Register, Rule};
+use crate::{
+ create_wrapper_type,
+ nlmsg::{NfNetlinkAttribute, NfNetlinkDeserializable},
+ parser::DecodeError,
+ sys,
+};
+use std::convert::TryFrom;
/// A meta expression refers to meta data associated with a packet.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[repr(u32)]
#[non_exhaustive]
-pub enum Meta {
+pub enum MetaType {
/// Packet ethertype protocol (skb->protocol), invalid in OUTPUT.
- Protocol,
+ Protocol = sys::NFT_META_PROTOCOL,
/// Packet mark.
- Mark { set: bool },
+ Mark = sys::NFT_META_MARK,
/// Packet input interface index (dev->ifindex).
- Iif,
+ Iif = sys::NFT_META_IIF,
/// Packet output interface index (dev->ifindex).
- Oif,
+ Oif = sys::NFT_META_OIF,
/// Packet input interface name (dev->name).
- IifName,
+ IifName = sys::NFT_META_IIFNAME,
/// Packet output interface name (dev->name).
- OifName,
+ OifName = sys::NFT_META_OIFNAME,
/// Packet input interface type (dev->type).
- IifType,
+ IifType = sys::NFT_META_IFTYPE,
/// Packet output interface type (dev->type).
- OifType,
+ OifType = sys::NFT_META_OIFTYPE,
/// Originating socket UID (fsuid).
- SkUid,
+ SkUid = sys::NFT_META_SKUID,
/// Originating socket GID (fsgid).
- SkGid,
+ SkGid = sys::NFT_META_SKGID,
/// Netfilter protocol (Transport layer protocol).
- NfProto,
+ NfProto = sys::NFT_META_NFPROTO,
/// Layer 4 protocol number.
- L4Proto,
+ L4Proto = sys::NFT_META_L4PROTO,
/// Socket control group (skb->sk->sk_classid).
- Cgroup,
+ Cgroup = sys::NFT_META_CGROUP,
/// A 32bit pseudo-random number.
- PRandom,
+ PRandom = sys::NFT_META_PRANDOM,
}
-impl Meta {
- /// Returns the corresponding `NFT_*` constant for this meta expression.
- pub fn to_raw_key(&self) -> u32 {
- use Meta::*;
- match *self {
- Protocol => libc::NFT_META_PROTOCOL as u32,
- Mark { .. } => libc::NFT_META_MARK as u32,
- Iif => libc::NFT_META_IIF as u32,
- Oif => libc::NFT_META_OIF as u32,
- IifName => libc::NFT_META_IIFNAME as u32,
- OifName => libc::NFT_META_OIFNAME as u32,
- IifType => libc::NFT_META_IIFTYPE as u32,
- OifType => libc::NFT_META_OIFTYPE as u32,
- SkUid => libc::NFT_META_SKUID as u32,
- SkGid => libc::NFT_META_SKGID as u32,
- NfProto => libc::NFT_META_NFPROTO as u32,
- L4Proto => libc::NFT_META_L4PROTO as u32,
- Cgroup => libc::NFT_META_CGROUP as u32,
- PRandom => libc::NFT_META_PRANDOM as u32,
- }
+impl NfNetlinkAttribute for MetaType {
+ fn get_size(&self) -> usize {
+ (*self as u32).get_size()
}
- fn from_raw(val: u32) -> Result<Self, DeserializationError> {
- match val as i32 {
- libc::NFT_META_PROTOCOL => Ok(Self::Protocol),
- libc::NFT_META_MARK => Ok(Self::Mark { set: false }),
- libc::NFT_META_IIF => Ok(Self::Iif),
- libc::NFT_META_OIF => Ok(Self::Oif),
- libc::NFT_META_IIFNAME => Ok(Self::IifName),
- libc::NFT_META_OIFNAME => Ok(Self::OifName),
- libc::NFT_META_IIFTYPE => Ok(Self::IifType),
- libc::NFT_META_OIFTYPE => Ok(Self::OifType),
- libc::NFT_META_SKUID => Ok(Self::SkUid),
- libc::NFT_META_SKGID => Ok(Self::SkGid),
- libc::NFT_META_NFPROTO => Ok(Self::NfProto),
- libc::NFT_META_L4PROTO => Ok(Self::L4Proto),
- libc::NFT_META_CGROUP => Ok(Self::Cgroup),
- libc::NFT_META_PRANDOM => Ok(Self::PRandom),
- _ => Err(DeserializationError::InvalidValue),
- }
+ unsafe fn write_payload(&self, addr: *mut u8) {
+ (*self as u32).write_payload(addr);
}
}
-impl Expression for Meta {
- fn get_raw_name() -> *const libc::c_char {
- b"meta\0" as *const _ as *const c_char
- }
-
- fn from_expr(expr: *const sys::nftnl_expr) -> Result<Self, DeserializationError>
- where
- Self: Sized,
- {
- unsafe {
- let mut ret = Self::from_raw(sys::nftnl_expr_get_u32(
- expr,
- sys::NFTNL_EXPR_META_KEY as u16,
- ))?;
-
- if let Self::Mark { ref mut set } = ret {
- *set = sys::nftnl_expr_is_set(expr, sys::NFTNL_EXPR_META_SREG as u16);
- }
-
- Ok(ret)
- }
+impl NfNetlinkDeserializable for MetaType {
+ fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
+ let (v, remaining_data) = u32::deserialize(buf)?;
+ Ok((
+ match v {
+ sys::NFT_META_PROTOCOL => Self::Protocol,
+ sys::NFT_META_MARK => Self::Mark,
+ sys::NFT_META_IIF => Self::Iif,
+ sys::NFT_META_OIF => Self::Oif,
+ sys::NFT_META_IIFNAME => Self::IifName,
+ sys::NFT_META_OIFNAME => Self::OifName,
+ sys::NFT_META_IFTYPE => Self::IifType,
+ sys::NFT_META_OIFTYPE => Self::OifType,
+ sys::NFT_META_SKUID => Self::SkUid,
+ sys::NFT_META_SKGID => Self::SkGid,
+ sys::NFT_META_NFPROTO => Self::NfProto,
+ sys::NFT_META_L4PROTO => Self::L4Proto,
+ sys::NFT_META_CGROUP => Self::Cgroup,
+ sys::NFT_META_PRANDOM => Self::PRandom,
+ value => return Err(DecodeError::UnknownMetaType(value)),
+ },
+ remaining_data,
+ ))
}
+}
- fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr {
- unsafe {
- let expr = try_alloc!(sys::nftnl_expr_alloc(Self::get_raw_name()));
+create_wrapper_type!(
+ inline: Meta,
+ [
+ (
+ get_dreg,
+ set_dreg,
+ with_dreg,
+ sys::NFTA_META_DREG,
+ dreg,
+ Register
+ ),
+ (
+ get_key,
+ set_key,
+ with_key,
+ sys::NFTA_META_KEY,
+ key,
+ MetaType
+ ),
+ (
+ get_sreg,
+ set_sreg,
+ with_sreg,
+ sys::NFTA_META_SREG,
+ sreg,
+ Register
+ )
+ ]
+);
- if let Meta::Mark { set: true } = self {
- sys::nftnl_expr_set_u32(
- expr,
- sys::NFTNL_EXPR_META_SREG as u16,
- libc::NFT_REG_1 as u32,
- );
- } else {
- sys::nftnl_expr_set_u32(
- expr,
- sys::NFTNL_EXPR_META_DREG as u16,
- libc::NFT_REG_1 as u32,
- );
- }
- sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_META_KEY as u16, self.to_raw_key());
- expr
- }
+impl Expression for Meta {
+ fn get_name() -> &'static str {
+ "meta"
}
}
-
-#[macro_export]
-macro_rules! nft_expr_meta {
- (proto) => {
- $crate::expr::Meta::Protocol
- };
- (mark set) => {
- $crate::expr::Meta::Mark { set: true }
- };
- (mark) => {
- $crate::expr::Meta::Mark { set: false }
- };
- (iif) => {
- $crate::expr::Meta::Iif
- };
- (oif) => {
- $crate::expr::Meta::Oif
- };
- (iifname) => {
- $crate::expr::Meta::IifName
- };
- (oifname) => {
- $crate::expr::Meta::OifName
- };
- (iiftype) => {
- $crate::expr::Meta::IifType
- };
- (oiftype) => {
- $crate::expr::Meta::OifType
- };
- (skuid) => {
- $crate::expr::Meta::SkUid
- };
- (skgid) => {
- $crate::expr::Meta::SkGid
- };
- (nfproto) => {
- $crate::expr::Meta::NfProto
- };
- (l4proto) => {
- $crate::expr::Meta::L4Proto
- };
- (cgroup) => {
- $crate::expr::Meta::Cgroup
- };
- (random) => {
- $crate::expr::Meta::PRandom
- };
-}
diff --git a/src/expr/mod.rs b/src/expr/mod.rs
index 78b1717..6dfa6c7 100644
--- a/src/expr/mod.rs
+++ b/src/expr/mod.rs
@@ -12,14 +12,13 @@ use std::net::Ipv6Addr;
use std::slice::Iter;
use super::rule::Rule;
+use crate::create_wrapper_type;
use crate::nlmsg::AttributeDecoder;
use crate::nlmsg::NfNetlinkAttribute;
-use crate::nlmsg::NfNetlinkAttributes;
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::AttributeType;
use crate::parser::DecodeError;
use crate::parser::InnerFormat;
use crate::sys::{self, nlattr};
@@ -52,10 +51,12 @@ pub use self::lookup::*;
mod masquerade;
pub use self::masquerade::*;
+*/
mod meta;
pub use self::meta::*;
+/*
mod nat;
pub use self::nat::*;
@@ -111,91 +112,15 @@ pub trait Expression {
fn get_name() -> &'static str;
}
-// wrapper for the general case, as we need to create many holder types given the depth of some
-// netlink expressions
-#[macro_export]
-macro_rules! create_expr_type {
- (without_decoder : $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
- #[derive(Clone, PartialEq, Eq)]
- pub struct $struct {
- inner: $crate::nlmsg::NfNetlinkAttributes,
- }
-
-
- $crate::impl_attr_getters_and_setters!(without_decoder $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
-
- impl std::fmt::Debug for $struct {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- use $crate::parser::InnerFormat;
- self.inner_format_struct(f.debug_struct(stringify!($struct)))?
- .finish()
- }
- }
-
-
- impl $crate::nlmsg::NfNetlinkDeserializable for $struct {
- fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), $crate::parser::DecodeError> {
- let reader = $crate::parser::NfNetlinkAttributeReader::new(buf, buf.len())?;
- let inner = reader.decode::<Self>()?;
- Ok(($struct { inner }, &[]))
- }
- }
-
- };
- ($struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
- create_expr_type!(without_decoder : $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
- $crate::impl_attr_getters_and_setters!(decoder $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
- };
- (with_builder : $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
- create_expr_type!($struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
-
- impl $struct {
- pub fn builder() -> Self {
- Self { inner: $crate::nlmsg::NfNetlinkAttributes::new() }
- }
- }
- };
- (inline $($($attrs:ident) +)? : $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
- create_expr_type!($($($attrs) + :)? $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
-
- impl $crate::nlmsg::NfNetlinkAttribute for $struct {
- fn get_size(&self) -> usize {
- self.inner.get_size()
- }
-
- unsafe fn write_payload(&self, addr: *mut u8) {
- self.inner.write_payload(addr)
- }
- }
- };
- (nested $($($attrs:ident) +)? : $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
- create_expr_type!($($($attrs) + :)? $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
-
- impl $crate::nlmsg::NfNetlinkAttribute for $struct {
- fn is_nested(&self) -> bool {
- true
- }
-
- fn get_size(&self) -> usize {
- self.inner.get_size()
- }
-
- unsafe fn write_payload(&self, addr: *mut u8) {
- self.inner.write_payload(addr)
- }
- }
- };
-}
-
-create_expr_type!(
- nested without_decoder : ExpressionHolder, [
+create_wrapper_type!(
+ nested without_deser : RawExpression, [
// Define the action netfilter will apply to packets processed by this chain, but that did not match any rules in it.
(
get_name,
set_name,
with_name,
sys::NFTA_EXPR_NAME,
- String,
+ name,
String
),
(
@@ -203,22 +128,20 @@ create_expr_type!(
set_data,
with_data,
sys::NFTA_EXPR_DATA,
- ExpressionVariant,
+ data,
ExpressionVariant
)
]);
-impl ExpressionHolder {
+impl RawExpression {
pub fn new<T>(expr: T) -> Self
where
T: Expression,
ExpressionVariant: From<T>,
{
- ExpressionHolder {
- inner: NfNetlinkAttributes::new(),
- }
- .with_name(T::get_name())
- .with_data(ExpressionVariant::from(expr))
+ RawExpression::default()
+ .with_name(T::get_name())
+ .with_data(ExpressionVariant::from(expr))
}
}
@@ -262,44 +185,45 @@ macro_rules! create_expr_variant {
}
)+
- impl AttributeDecoder for ExpressionHolder {
+ impl $crate::nlmsg::AttributeDecoder for RawExpression {
fn decode_attribute(
- attrs: &NfNetlinkAttributes,
+ &mut self,
attr_type: u16,
buf: &[u8],
- ) -> Result<AttributeType, DecodeError> {
+ ) -> Result<(), $crate::parser::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(DecodeError::InvalidDataSize);
+ return Err($crate::parser::DecodeError::InvalidDataSize);
}
- Ok(AttributeType::String(val))
+ self.name = Some(val);
+ Ok(())
},
x if x == sys::NFTA_EXPR_DATA => {
// we can assume we have already the name parsed, as that's how we identify the
// type of expression
- let name = attrs
- .get_attr(sys::NFTA_EXPR_NAME)
- .ok_or(DecodeError::MissingExpressionName)?;
+ let name = self.name.as_ref()
+ .ok_or($crate::parser::DecodeError::MissingExpressionName)?;
match name {
$(
- AttributeType::String(x) if x == <$type>::get_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);
}
- Ok(AttributeType::ExpressionVariant(ExpressionVariant::from(res)))
+ self.data = Some(ExpressionVariant::from(res));
+ Ok(())
},
)+
- AttributeType::String(name) => {
+ name => {
info!("Unrecognized expression '{}', generating an ExpressionRaw", name);
- ExpressionRaw::deserialize(buf).map(|(res, _)| AttributeType::ExpressionVariant(ExpressionVariant::ExpressionRaw(res)))
- },
- _ => unreachable!()
+ self.data = Some(ExpressionVariant::ExpressionRaw(ExpressionRaw::deserialize(buf)?.0));
+ Ok(())
+ }
}
},
_ => Err(DecodeError::UnsupportedAttributeType(attr_type)),
@@ -314,12 +238,13 @@ create_expr_variant!(
[Log, Log],
[Immediate, Immediate],
[Bitwise, Bitwise],
- [ExpressionRaw, ExpressionRaw]
+ [ExpressionRaw, ExpressionRaw],
+ [Meta, Meta]
);
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct ExpressionList {
- exprs: Vec<AttributeType>,
+ exprs: Vec<RawExpression>,
}
impl ExpressionList {
@@ -327,9 +252,9 @@ 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));
+ /// 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)
@@ -337,8 +262,7 @@ impl ExpressionList {
T: Expression,
ExpressionVariant: From<T>,
{
- self.exprs
- .push(AttributeType::Expression(ExpressionHolder::new(e)));
+ self.exprs.push(RawExpression::new(e));
}
pub fn with_expression<T>(mut self, e: T) -> Self
@@ -351,10 +275,7 @@ impl ExpressionList {
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a ExpressionVariant> {
- self.exprs.iter().map(|t| match t {
- AttributeType::Expression(e) => e.get_data().unwrap(),
- _ => unreachable!(),
- })
+ self.exprs.iter().map(|e| e.get_data().unwrap())
}
}
@@ -392,13 +313,13 @@ impl NfNetlinkDeserializable for ExpressionList {
return Err(DecodeError::UnsupportedAttributeType(nla_type));
}
- let (expr, remaining) = ExpressionHolder::deserialize(
+ 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(AttributeType::Expression(expr));
+ exprs.push(expr);
pos += pad_netlink_object_with_variable_size(nlattr.nla_len as usize);
}
@@ -411,15 +332,27 @@ impl NfNetlinkDeserializable for ExpressionList {
}
}
-create_expr_type!(
- nested with_builder : ExpressionData,
+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(),
+ }
+ }
+}
+
+create_wrapper_type!(
+ nested : ExpressionData,
[
(
get_value,
set_value,
with_value,
sys::NFTA_DATA_VALUE,
- VecU8,
+ value,
Vec<u8>
),
(
@@ -427,7 +360,7 @@ create_expr_type!(
set_verdict,
with_verdict,
sys::NFTA_DATA_VERDICT,
- ExprVerdictAttribute,
+ verdict,
VerdictAttribute
)
]
@@ -454,7 +387,7 @@ impl NfNetlinkDeserializable for ExpressionRaw {
}
// 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
+// where deserializing a message and then reserializing it is invalid
impl Expression for ExpressionRaw {
fn get_name() -> &'static str {
"unknown_expression"
diff --git a/src/expr/verdict.rs b/src/expr/verdict.rs
index 7c27af6..547ba91 100644
--- a/src/expr/verdict.rs
+++ b/src/expr/verdict.rs
@@ -4,7 +4,7 @@ use libc::{NF_ACCEPT, NF_DROP, NF_QUEUE};
use super::{ExpressionData, Immediate, Register};
use crate::{
- create_expr_type,
+ create_wrapper_type,
nlmsg::{NfNetlinkAttribute, NfNetlinkDeserializable},
parser::DecodeError,
sys::{self, NFT_BREAK, NFT_CONTINUE, NFT_GOTO, NFT_JUMP, NFT_RETURN},
@@ -53,15 +53,15 @@ impl NfNetlinkDeserializable for VerdictType {
}
}
-create_expr_type!(
- nested with_builder : VerdictAttribute,
+create_wrapper_type!(
+ nested: VerdictAttribute,
[
(
get_code,
set_code,
with_code,
sys::NFTA_VERDICT_CODE,
- ExprVerdictType,
+ code,
VerdictType
),
(
@@ -69,7 +69,7 @@ create_expr_type!(
set_chain,
with_chain,
sys::NFTA_VERDICT_CHAIN,
- String,
+ chain,
String
),
(
@@ -77,7 +77,7 @@ create_expr_type!(
set_chain_id,
with_chain_id,
sys::NFTA_VERDICT_CHAIN_ID,
- U32,
+ chain_id,
u32
)
]
@@ -113,12 +113,12 @@ impl Immediate {
VerdictKind::Goto { .. } => VerdictType::Goto,
VerdictKind::Return => VerdictType::Return,
};
- let mut data = VerdictAttribute::builder().with_code(code);
+ let mut data = VerdictAttribute::default().with_code(code);
if let VerdictKind::Jump { chain } | VerdictKind::Goto { chain } = kind {
data.set_chain(chain);
}
- Immediate::builder()
+ Immediate::default()
.with_dreg(Register::Verdict)
- .with_data(ExpressionData::builder().with_verdict(data))
+ .with_data(ExpressionData::default().with_verdict(data))
}
}
diff --git a/src/lib.rs b/src/lib.rs
index d02c785..044030f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -78,25 +78,11 @@ extern crate log;
pub mod sys;
use libc;
-use std::{convert::TryFrom, ffi::c_void, ops::Deref};
-
-macro_rules! try_alloc {
- ($e:expr) => {{
- let ptr = $e;
- if ptr.is_null() {
- // OOM, and the tried allocation was likely very small,
- // so we are in a very tight situation. We do what libstd does, aborts.
- std::process::abort();
- }
- ptr
- }};
-}
+use std::convert::TryFrom;
mod batch;
pub use batch::{default_batch_page_size, Batch};
-pub mod expr;
-
mod table;
pub use table::list_tables;
pub use table::Table;
@@ -117,6 +103,8 @@ mod rule;
pub use rule::list_rules_for_chain;
pub use rule::Rule;
+pub mod expr;
+
//mod rule_methods;
//pub use rule_methods::{iface_index, Error as MatchError, Protocol, RuleMethods};
@@ -155,6 +143,12 @@ pub enum ProtocolFamily {
DecNet = libc::NFPROTO_DECNET,
}
+impl Default for ProtocolFamily {
+ fn default() -> Self {
+ Self::Unspec
+ }
+}
+
impl TryFrom<i32> for ProtocolFamily {
type Error = DecodeError;
fn try_from(value: i32) -> Result<Self, Self::Error> {
diff --git a/src/nlmsg.rs b/src/nlmsg.rs
index 8960146..8563a37 100644
--- a/src/nlmsg.rs
+++ b/src/nlmsg.rs
@@ -1,12 +1,9 @@
-use std::{collections::BTreeMap, fmt::Debug, mem::size_of};
+use std::{fmt::Debug, mem::size_of};
use crate::{
- parser::{
- pad_netlink_object, pad_netlink_object_with_variable_size, write_attribute, AttributeType,
- DecodeError,
- },
+ parser::{pad_netlink_object, pad_netlink_object_with_variable_size, DecodeError},
sys::{
- nfgenmsg, nlattr, nlmsghdr, NFNETLINK_V0, NFNL_MSG_BATCH_BEGIN, NFNL_MSG_BATCH_END,
+ nfgenmsg, nlmsghdr, NFNETLINK_V0, NFNL_MSG_BATCH_BEGIN, NFNL_MSG_BATCH_END,
NFNL_SUBSYS_NFTABLES,
},
MsgType, ProtocolFamily,
@@ -88,11 +85,7 @@ impl<'a> NfNetlinkWriter<'a> {
}
pub trait AttributeDecoder {
- fn decode_attribute(
- attrs: &NfNetlinkAttributes,
- attr_type: u16,
- buf: &[u8],
- ) -> Result<AttributeType, DecodeError>;
+ fn decode_attribute(&mut self, attr_type: u16, buf: &[u8]) -> Result<(), DecodeError>;
}
pub trait NfNetlinkDeserializable: Sized {
@@ -119,6 +112,7 @@ pub trait NfNetlinkAttribute: Debug + Sized {
unsafe fn write_payload(&self, addr: *mut u8);
}
+/*
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NfNetlinkAttributes {
pub attributes: BTreeMap<NetlinkType, AttributeType>,
@@ -170,3 +164,4 @@ impl NfNetlinkAttribute for NfNetlinkAttributes {
}
}
}
+*/
diff --git a/src/parser.rs b/src/parser.rs
index 8b14d74..b7d0ac3 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -9,10 +9,9 @@ use std::{
use thiserror::Error;
use crate::{
- expr::ExpressionHolder,
+ //expr::ExpressionHolder,
nlmsg::{
- AttributeDecoder, NetlinkType, NfNetlinkAttribute, NfNetlinkAttributes,
- NfNetlinkDeserializable, NfNetlinkWriter,
+ AttributeDecoder, NetlinkType, NfNetlinkAttribute, NfNetlinkDeserializable, NfNetlinkWriter,
},
sys::{
nfgenmsg, nlattr, nlmsgerr, nlmsghdr, NFNETLINK_V0, NFNL_MSG_BATCH_BEGIN,
@@ -66,6 +65,9 @@ pub enum DecodeError {
#[error("Invalid policy for a chain")]
UnknownChainPolicy,
+ #[error("Unknown type for a Meta expression")]
+ UnknownMetaType(u32),
+
#[error("Invalid value for a register")]
UnknownRegisterValue,
@@ -208,7 +210,11 @@ pub fn parse_nlmsg<'a>(buf: &'a [u8]) -> Result<(nlmsghdr, NlMsg<'a>), DecodeErr
/// Write the attribute, preceded by a `libc::nlattr`
// rewrite of `mnl_attr_put`
-pub unsafe fn write_attribute<'a>(ty: NetlinkType, obj: &AttributeType, mut buf: *mut u8) {
+pub unsafe fn write_attribute<'a>(
+ ty: NetlinkType,
+ obj: &impl NfNetlinkAttribute,
+ mut buf: *mut u8,
+) {
let header_len = pad_netlink_object::<libc::nlattr>();
// copy the header
*(buf as *mut nlattr) = nlattr {
@@ -296,7 +302,6 @@ impl NfNetlinkDeserializable for u64 {
}
}
-// TODO: safe handling for null-delimited strings
impl NfNetlinkAttribute for String {
fn get_size(&self) -> usize {
self.len()
@@ -346,122 +351,42 @@ impl NfNetlinkDeserializable for ProtocolFamily {
}
}
-pub struct NfNetlinkAttributeReader<'a> {
- buf: &'a [u8],
- pos: usize,
- remaining_size: usize,
- attrs: NfNetlinkAttributes,
-}
-
-impl<'a> NfNetlinkAttributeReader<'a> {
- pub fn new(buf: &'a [u8], remaining_size: usize) -> Result<Self, DecodeError> {
- if buf.len() < remaining_size {
- return Err(DecodeError::BufTooSmall);
+pub(crate) fn read_attributes<T: AttributeDecoder + Default>(buf: &[u8]) -> Result<T, DecodeError> {
+ debug!(
+ "Calling <{} as NfNetlinkDeserialize>::deserialize()",
+ std::any::type_name::<T>()
+ );
+ let mut remaining_size = buf.len();
+ let mut pos = 0;
+ let mut res = T::default();
+ while remaining_size > 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;
+
+ pos += pad_netlink_object::<nlattr>();
+ let attr_remaining_size = nlattr.nla_len as usize - pad_netlink_object::<nlattr>();
+ match T::decode_attribute(&mut res, nla_type, &buf[pos..pos + attr_remaining_size]) {
+ Ok(()) => {}
+ Err(DecodeError::UnsupportedAttributeType(t)) => info!(
+ "Ignoring unsupported attribute type {} for type {}",
+ t,
+ std::any::type_name::<T>()
+ ),
+ Err(e) => return Err(e),
}
+ pos += pad_netlink_object_with_variable_size(attr_remaining_size);
- Ok(Self {
- buf,
- pos: 0,
- remaining_size,
- attrs: NfNetlinkAttributes::new(),
- })
+ remaining_size -= pad_netlink_object_with_variable_size(nlattr.nla_len as usize);
}
- pub fn get_raw_data(&self) -> &'a [u8] {
- &self.buf[self.pos..]
- }
-
- pub fn decode<T: AttributeDecoder + 'static>(
- mut self,
- ) -> Result<NfNetlinkAttributes, DecodeError> {
- debug!(
- "Calling NfNetlinkAttributeReader::decode() on {}",
- std::any::type_name::<T>()
- );
- while self.remaining_size > pad_netlink_object::<nlattr>() {
- let nlattr =
- unsafe { *transmute::<*const u8, *const nlattr>(self.buf[self.pos..].as_ptr()) };
- // ignore the byteorder and nested attributes
- let nla_type = nlattr.nla_type & NLA_TYPE_MASK as u16;
-
- self.pos += pad_netlink_object::<nlattr>();
- let attr_remaining_size = nlattr.nla_len as usize - pad_netlink_object::<nlattr>();
- match T::decode_attribute(
- &self.attrs,
- nla_type,
- &self.buf[self.pos..self.pos + attr_remaining_size],
- ) {
- Ok(x) => self.attrs.set_attr(nla_type, x),
- Err(DecodeError::UnsupportedAttributeType(t)) => info!(
- "Ignoring unsupported attribute type {} for type {}",
- t,
- std::any::type_name::<T>()
- ),
- Err(e) => return Err(e),
- }
- self.pos += pad_netlink_object_with_variable_size(attr_remaining_size);
-
- self.remaining_size -= pad_netlink_object_with_variable_size(nlattr.nla_len as usize);
- }
-
- if self.remaining_size != 0 {
- Err(DecodeError::InvalidDataSize)
- } else {
- Ok(self.attrs)
- }
+ if remaining_size != 0 {
+ Err(DecodeError::InvalidDataSize)
+ } else {
+ Ok(res)
}
}
-#[macro_export]
-macro_rules! impl_attribute_holder {
- ($enum_name:ident, $([$internal_name:ident, $type:ty]),+) => {
- #[derive(Debug, Clone, PartialEq, Eq)]
- pub enum $enum_name {
- $(
- $internal_name($type),
- )+
- }
-
- impl NfNetlinkAttribute for $enum_name {
- fn is_nested(&self) -> bool {
- match self {
- $(
- $enum_name::$internal_name(val) => val.is_nested()
- ),+
- }
- }
-
- fn get_size(&self) -> usize {
- match self {
- $(
- $enum_name::$internal_name(val) => val.get_size()
- ),+
- }
- }
-
- unsafe fn write_payload(&self, addr: *mut u8) {
- match self {
- $(
- $enum_name::$internal_name(val) => val.write_payload(addr)
- ),+
- }
- }
- }
-
- impl $enum_name {
- $(
- #[allow(non_snake_case)]
- pub fn $internal_name(&self) -> Option<&$type> {
- match self {
- $enum_name::$internal_name(val) => Some(val),
- _ => None
- }
- }
- )+
- }
- };
-}
-
pub trait InnerFormat {
fn inner_format_struct<'a, 'b: 'a>(
&'a self,
@@ -469,49 +394,24 @@ pub trait InnerFormat {
) -> Result<DebugStruct<'a, 'b>, std::fmt::Error>;
}
-impl_attribute_holder!(
- AttributeType,
- [String, String],
- [U8, u8],
- [U16, u16],
- [I32, i32],
- [U32, u32],
- [U64, u64],
- [VecU8, Vec<u8>],
- [ChainHook, crate::chain::Hook],
- [ChainPolicy, crate::chain::ChainPolicy],
- [ChainType, crate::chain::ChainType],
- [ProtocolFamily, crate::ProtocolFamily],
- [Expression, crate::expr::ExpressionHolder],
- [ExpressionVariant, crate::expr::ExpressionVariant],
- [ExpressionList, crate::expr::ExpressionList],
- [ExprLog, crate::expr::Log],
- [ExprImmediate, crate::expr::Immediate],
- [ExprData, crate::expr::ExpressionData],
- [ExprVerdictAttribute, crate::expr::VerdictAttribute],
- [ExprVerdictType, crate::expr::VerdictType],
- [Register, crate::expr::Register],
- [ExprRaw, crate::expr::ExpressionRaw]
-);
-
#[macro_export]
macro_rules! impl_attr_getters_and_setters {
- (without_decoder $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
+ (without_deser $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
impl $struct {
$(
#[allow(dead_code)]
pub fn $getter_name(&self) -> Option<&$type> {
- self.inner.get_attr($attr_name as $crate::nlmsg::NetlinkType).map(|x| x.$internal_name()).flatten()
+ self.$internal_name.as_ref()
}
#[allow(dead_code)]
pub fn $setter_name(&mut self, val: impl Into<$type>) {
- self.inner.set_attr($attr_name as $crate::nlmsg::NetlinkType, $crate::parser::AttributeType::$internal_name(val.into()));
+ self.$internal_name = Some(val.into());
}
#[allow(dead_code)]
pub fn $in_place_edit_name(mut self, val: impl Into<$type>) -> Self {
- self.inner.set_attr($attr_name as $crate::nlmsg::NetlinkType, $crate::parser::AttributeType::$internal_name(val.into()));
+ self.$internal_name = Some(val.into());
self
}
@@ -540,10 +440,10 @@ macro_rules! impl_attr_getters_and_setters {
}
};
- (decoder $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
+ (deser $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
impl $crate::nlmsg::AttributeDecoder for $struct {
#[allow(dead_code)]
- fn decode_attribute(_attrs: &$crate::nlmsg::NfNetlinkAttributes, attr_type: u16, buf: &[u8]) -> Result<$crate::parser::AttributeType, $crate::parser::DecodeError> {
+ fn decode_attribute(&mut self, attr_type: u16, buf: &[u8]) -> Result<(), $crate::parser::DecodeError> {
use $crate::nlmsg::NfNetlinkDeserializable;
debug!("Decoding attribute {} in type {}", attr_type, std::any::type_name::<$struct>());
match attr_type {
@@ -554,7 +454,8 @@ macro_rules! impl_attr_getters_and_setters {
if remaining.len() != 0 {
return Err($crate::parser::DecodeError::InvalidDataSize);
}
- Ok($crate::parser::AttributeType::$internal_name(val))
+ self.$setter_name(val);
+ Ok(())
},
)+
_ => Err($crate::parser::DecodeError::UnsupportedAttributeType(attr_type)),
@@ -563,39 +464,168 @@ macro_rules! impl_attr_getters_and_setters {
}
};
($struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
- $crate::impl_attr_getters_and_setters!(without_decoder $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
- $crate::impl_attr_getters_and_setters!(decoder $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
+ $crate::impl_attr_getters_and_setters!(without_deser $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
+ $crate::impl_attr_getters_and_setters!(deser $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
};
}
-pub fn parse_object<T: AttributeDecoder + 'static>(
- buf: &[u8],
- add_obj: u32,
- del_obj: u32,
-) -> Result<(NfNetlinkAttributes, nfgenmsg, &[u8]), DecodeError> {
- debug!("parse_object() running");
- let (hdr, msg) = parse_nlmsg(buf)?;
+pub trait Parsable
+where
+ Self: Sized,
+{
+ fn parse_object(
+ buf: &[u8],
+ add_obj: u32,
+ del_obj: u32,
+ ) -> Result<(Self, nfgenmsg, &[u8]), DecodeError>;
+}
+
+impl<T> Parsable for T
+where
+ T: AttributeDecoder + Default + Sized,
+{
+ fn parse_object(
+ buf: &[u8],
+ add_obj: u32,
+ del_obj: u32,
+ ) -> Result<(Self, nfgenmsg, &[u8]), DecodeError> {
+ debug!("parse_object() started");
+ let (hdr, msg) = parse_nlmsg(buf)?;
+
+ let op = get_operation_from_nlmsghdr_type(hdr.nlmsg_type) as u32;
+
+ if op != add_obj && op != del_obj {
+ return Err(DecodeError::UnexpectedType(hdr.nlmsg_type));
+ }
+
+ let obj_size = hdr.nlmsg_len as usize
+ - pad_netlink_object_with_variable_size(size_of::<nlmsghdr>() + size_of::<nfgenmsg>());
- let op = get_operation_from_nlmsghdr_type(hdr.nlmsg_type) as u32;
+ let remaining_data_offset = pad_netlink_object_with_variable_size(hdr.nlmsg_len as usize);
+ let remaining_data = &buf[remaining_data_offset..];
- if op != add_obj && op != del_obj {
- return Err(DecodeError::UnexpectedType(hdr.nlmsg_type));
+ let (nfgenmsg, res) = match msg {
+ NlMsg::NfGenMsg(nfgenmsg, content) => {
+ (nfgenmsg, read_attributes(&content[..obj_size])?)
+ }
+ _ => return Err(DecodeError::UnexpectedType(hdr.nlmsg_type)),
+ };
+
+ Ok((res, nfgenmsg, remaining_data))
}
+}
+
+#[macro_export]
+macro_rules! impl_nfnetlinkattribute {
+ (__inner : $struct:ident, [$(($attr_name:expr, $internal_name:ident)),+]) => {
+ impl $struct {
+ fn inner_get_size(&self) -> usize {
+ use $crate::nlmsg::NfNetlinkAttribute;
+ use $crate::parser::{pad_netlink_object, pad_netlink_object_with_variable_size};
+ use $crate::sys::nlattr;
+ let mut size = 0;
+
+ $(
+ if let Some(val) = &self.$internal_name {
+ // Attribute header + attribute value
+ size += pad_netlink_object::<nlattr>()
+ + pad_netlink_object_with_variable_size(val.get_size());
+ }
+ )+
+
+ size
+ }
+
+ unsafe fn inner_write_payload(&self, mut addr: *mut u8) {
+ use $crate::nlmsg::NfNetlinkAttribute;
+ use $crate::parser::{pad_netlink_object, pad_netlink_object_with_variable_size};
+ use $crate::sys::nlattr;
+ $(
+ if let Some(val) = &self.$internal_name {
+ debug!("writing attribute {} - {:?}", $attr_name, val);
+
+ unsafe {
+ $crate::parser::write_attribute($attr_name, val, addr);
+ }
+ let size = pad_netlink_object::<nlattr>()
+ + pad_netlink_object_with_variable_size(val.get_size());
+ #[allow(unused)]
+ {
+ addr = addr.offset(size as isize);
+ }
+ }
+ )+
+ }
+ }
+ };
+ (inline : $struct:ident, [$(($attr_name:expr, $internal_name:ident)),+]) => {
+ $crate::impl_nfnetlinkattribute!(__inner : $struct, [$(($attr_name, $internal_name)),+]);
+
+ impl $crate::nlmsg::NfNetlinkAttribute for $struct {
+ fn get_size(&self) -> usize {
+ self.inner_get_size()
+ }
+
+ unsafe fn write_payload(&self, addr: *mut u8) {
+ self.inner_write_payload(addr);
+ }
+ }
+ };
+ (nested : $struct:ident, [$(($attr_name:expr, $internal_name:ident)),+]) => {
+ $crate::impl_nfnetlinkattribute!(__inner : $struct, [$(($attr_name, $internal_name)),+]);
- let obj_size = hdr.nlmsg_len as usize
- - pad_netlink_object_with_variable_size(size_of::<nlmsghdr>() + size_of::<nfgenmsg>());
+ impl $crate::nlmsg::NfNetlinkAttribute for $struct {
+ fn is_nested(&self) -> bool {
+ true
+ }
- let remaining_data_offset = pad_netlink_object_with_variable_size(hdr.nlmsg_len as usize);
- let remaining_data = &buf[remaining_data_offset..];
+ fn get_size(&self) -> usize {
+ self.inner_get_size()
+ }
- let (nfgenmsg, attrs) = match msg {
- NlMsg::NfGenMsg(nfgenmsg, content) => {
- (nfgenmsg, NfNetlinkAttributeReader::new(content, obj_size)?)
+ unsafe fn write_payload(&self, addr: *mut u8) {
+ self.inner_write_payload(addr);
+ }
}
- _ => return Err(DecodeError::UnexpectedType(hdr.nlmsg_type)),
};
+}
- let inner = attrs.decode::<T>()?;
+#[macro_export]
+macro_rules! create_wrapper_type {
+ (without_deser : $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
+ #[derive(Clone, PartialEq, Eq, Default)]
+ pub struct $struct {
+ $(
+ $internal_name: Option<$type>
+ ),+
+ }
- Ok((inner, nfgenmsg, remaining_data))
+ $crate::impl_attr_getters_and_setters!(without_deser $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
+
+ impl std::fmt::Debug for $struct {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ use $crate::parser::InnerFormat;
+ self.inner_format_struct(f.debug_struct(stringify!($struct)))?
+ .finish()
+ }
+ }
+
+ impl $crate::nlmsg::NfNetlinkDeserializable for $struct {
+ fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), $crate::parser::DecodeError> {
+ Ok(($crate::parser::read_attributes(buf)?, &[]))
+ }
+ }
+ };
+ ($struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
+ create_wrapper_type!(without_deser : $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
+ $crate::impl_attr_getters_and_setters!(deser $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
+ };
+ (inline $($($attrs:ident) +)? : $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
+ create_wrapper_type!($($($attrs) + :)? $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
+ $crate::impl_nfnetlinkattribute!(inline : $struct, [$(($attr_name, $internal_name)),+]);
+ };
+ (nested $($($attrs:ident) +)? : $struct:ident, [$(($getter_name:ident, $setter_name:ident, $in_place_edit_name:ident, $attr_name:expr, $internal_name:ident, $type:ty)),+]) => {
+ create_wrapper_type!($($($attrs) + :)? $struct, [$(($getter_name, $setter_name, $in_place_edit_name, $attr_name, $internal_name, $type)),+]);
+ $crate::impl_nfnetlinkattribute!(nested : $struct, [$(($attr_name, $internal_name)),+]);
+ };
}
diff --git a/src/query.rs b/src/query.rs
index 8ea7b89..294cbfe 100644
--- a/src/query.rs
+++ b/src/query.rs
@@ -1,7 +1,7 @@
use std::os::unix::prelude::RawFd;
use crate::{
- nlmsg::{NfNetlinkAttributes, NfNetlinkObject, NfNetlinkWriter},
+ nlmsg::{NfNetlinkAttribute, NfNetlinkObject, NfNetlinkWriter},
parser::{nft_nlmsg_maxsize, pad_netlink_object_with_variable_size},
sys::{nlmsgerr, NLM_F_DUMP, NLM_F_MULTI},
ProtocolFamily,
@@ -152,10 +152,10 @@ where
/// Returns a buffer containing a netlink message which requests a list of all the netfilter
/// matching objects (e.g. tables, chains, rules, ...).
/// Supply the type of objects to retrieve (e.g. libc::NFT_MSG_GETTABLE), and a search filter.
-pub fn get_list_of_objects(
+pub fn get_list_of_objects<T: NfNetlinkAttribute>(
msg_type: u16,
seq: u32,
- filter: Option<&NfNetlinkAttributes>,
+ filter: Option<&T>,
) -> Result<Vec<u8>, Error> {
let mut buffer = Vec::new();
let mut writer = NfNetlinkWriter::new(&mut buffer);
@@ -167,7 +167,10 @@ pub fn get_list_of_objects(
None,
);
if let Some(filter) = filter {
- filter.serialize(&mut writer);
+ let buf = writer.add_data_zeroed(filter.get_size());
+ unsafe {
+ filter.write_payload(buf.as_mut_ptr());
+ }
}
writer.finalize_writing_object();
Ok(buffer)
@@ -180,11 +183,11 @@ pub fn get_list_of_objects(
pub fn list_objects_with_data<'a, Object, Accumulator>(
data_type: u16,
cb: &dyn Fn(Object, &mut Accumulator) -> Result<(), Error>,
- filter: Option<&NfNetlinkAttributes>,
+ filter: Option<&Object>,
working_data: &'a mut Accumulator,
) -> Result<(), Error>
where
- Object: NfNetlinkObject,
+ Object: NfNetlinkObject + NfNetlinkAttribute,
{
debug!("Listing objects of kind {}", data_type);
let sock = socket::socket(
diff --git a/src/rule.rs b/src/rule.rs
index a596fce..5f2889e 100644
--- a/src/rule.rs
+++ b/src/rule.rs
@@ -1,20 +1,23 @@
use crate::expr::ExpressionList;
-use crate::nlmsg::{
- NfNetlinkAttributes, NfNetlinkDeserializable, NfNetlinkObject, NfNetlinkWriter,
-};
-use crate::parser::InnerFormat;
-use crate::parser::{parse_object, DecodeError};
+use crate::nlmsg::{NfNetlinkAttribute, NfNetlinkDeserializable, NfNetlinkObject, NfNetlinkWriter};
+use crate::parser::{DecodeError, InnerFormat, Parsable};
use crate::query::list_objects_with_data;
use crate::sys::{self, NFT_MSG_DELRULE, NFT_MSG_NEWRULE, NLM_F_ACK, NLM_F_CREATE};
use crate::{chain::Chain, MsgType};
-use crate::{impl_attr_getters_and_setters, ProtocolFamily};
+use crate::{impl_attr_getters_and_setters, impl_nfnetlinkattribute, ProtocolFamily};
use std::convert::TryFrom;
use std::fmt::Debug;
/// A nftables firewall rule.
-#[derive(PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq, Default)]
pub struct Rule {
- inner: NfNetlinkAttributes,
+ id: Option<u32>,
+ handle: Option<u64>,
+ position: Option<u64>,
+ table: Option<String>,
+ chain: Option<String>,
+ userdata: Option<Vec<u8>>,
+ expressions: Option<ExpressionList>,
family: ProtocolFamily,
}
@@ -23,21 +26,18 @@ impl Rule {
///
/// [`Chain`]: struct.Chain.html
pub fn new(chain: &Chain) -> Result<Rule, DecodeError> {
- let inner = NfNetlinkAttributes::new();
- Ok(Rule {
- inner,
- family: chain.get_family(),
- }
- .with_table(
- chain
- .get_table()
- .ok_or(DecodeError::MissingChainInformationError)?,
- )
- .with_chain(
- chain
- .get_name()
- .ok_or(DecodeError::MissingChainInformationError)?,
- ))
+ Ok(Rule::default()
+ .with_family(chain.get_family())
+ .with_table(
+ chain
+ .get_table()
+ .ok_or(DecodeError::MissingChainInformationError)?,
+ )
+ .with_chain(
+ chain
+ .get_name()
+ .ok_or(DecodeError::MissingChainInformationError)?,
+ ))
}
pub fn get_family(&self) -> ProtocolFamily {
@@ -53,10 +53,6 @@ impl Rule {
self
}
- fn raw_attributes(&self) -> &NfNetlinkAttributes {
- &self.inner
- }
-
/*
/// Adds an expression to this rule. Expressions are evaluated from first to last added.
/// As soon as an expression does not match the packet it's being evaluated for, evaluation
@@ -191,143 +187,58 @@ impl NfNetlinkObject for Rule {
seq,
None,
);
- self.inner.serialize(writer);
+ let buf = writer.add_data_zeroed(self.get_size());
+ unsafe {
+ self.write_payload(buf.as_mut_ptr());
+ }
writer.finalize_writing_object();
}
}
impl NfNetlinkDeserializable for Rule {
fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
- let (inner, nfgenmsg, remaining_data) =
- parse_object::<Self>(buf, NFT_MSG_NEWRULE, NFT_MSG_DELRULE)?;
+ let (mut obj, nfgenmsg, remaining_data) =
+ Self::parse_object(buf, NFT_MSG_NEWRULE, NFT_MSG_DELRULE)?;
+ obj.family = ProtocolFamily::try_from(nfgenmsg.nfgen_family as i32)?;
- Ok((
- Self {
- inner,
- family: ProtocolFamily::try_from(nfgenmsg.nfgen_family as i32)?,
- },
- remaining_data,
- ))
+ Ok((obj, remaining_data))
}
}
impl_attr_getters_and_setters!(
Rule,
[
- (get_id, set_id, with_id, sys::NFTA_RULE_ID, U32, u32),
- (get_handle, set_handle, with_handle, sys::NFTA_RULE_HANDLE, U64, u64),
+ (get_table, set_table, with_table, sys::NFTA_RULE_TABLE, table, String),
+ (get_chain, set_chain, with_chain, sys::NFTA_RULE_CHAIN, chain, String),
+ (get_handle, set_handle, with_handle, sys::NFTA_RULE_HANDLE, handle, u64),
+ (get_expressions, set_expressions, with_expressions, sys::NFTA_RULE_EXPRESSIONS, expressions, ExpressionList),
// Sets the position of this rule within the chain it lives in. By default a new rule is added
// to the end of the chain.
- (get_position, set_position, with_position, sys::NFTA_RULE_POSITION, U64, u64),
- (get_table, set_table, with_table, sys::NFTA_RULE_TABLE, String, String),
- (get_chain, set_chain, with_chain, sys::NFTA_RULE_CHAIN, String, String),
+ (get_position, set_position, with_position, sys::NFTA_RULE_POSITION, position, u64),
(
get_userdata,
set_userdata,
with_userdata,
sys::NFTA_RULE_USERDATA,
- VecU8,
+ userdata,
Vec<u8>
),
- (get_expressions, set_expressions, with_expressions, sys::NFTA_RULE_EXPRESSIONS, ExpressionList, ExpressionList)
+ (get_id, set_id, with_id, sys::NFTA_RULE_ID, id, u32)
]
);
-/*
-
-impl PartialEq for Rule {
- fn eq(&self, other: &Self) -> bool {
- if self.get_chain() != other.get_chain() {
- return false;
- }
-
- unsafe {
- if sys::nftnl_rule_is_set(self.rule, sys::NFTNL_RULE_HANDLE as u16)
- && sys::nftnl_rule_is_set(other.rule, sys::NFTNL_RULE_HANDLE as u16)
- {
- if self.get_handle() != other.get_handle() {
- return false;
- }
- }
- if sys::nftnl_rule_is_set(self.rule, sys::NFTNL_RULE_POSITION as u16)
- && sys::nftnl_rule_is_set(other.rule, sys::NFTNL_RULE_POSITION as u16)
- {
- if self.get_position() != other.get_position() {
- return false;
- }
- }
- }
-
- return false;
- }
-}
-
-unsafe impl NlMsg for Rule {
- unsafe fn write(&self, buf: &mut Vec<u8>, seq: u32, msg_type: MsgType) {
- let type_ = match msg_type {
- MsgType::Add => libc::NFT_MSG_NEWRULE,
- MsgType::Del => libc::NFT_MSG_DELRULE,
- };
- let flags: u16 = match msg_type {
- MsgType::Add => (libc::NLM_F_CREATE | libc::NLM_F_APPEND | libc::NLM_F_EXCL) as u16,
- MsgType::Del => 0u16,
- } | libc::NLM_F_ACK as u16;
- /*
- let header = sys::nftnl_nlmsg_build_hdr(
- buf as *mut c_char,
- type_ as u16,
- self.chain.get_table().get_family() as u16,
- flags,
- seq,
- );
- sys::nftnl_rule_nlmsg_build_payload(header, self.rule);
- */
- }
-}
-
-impl Drop for Rule {
- fn drop(&mut self) {
- unsafe { sys::nftnl_rule_free(self.rule) };
- }
-}
-
-pub struct RuleExprsIter {
- rule: Rc<Rule>,
- iter: *mut sys::nftnl_expr_iter,
-}
-
-impl RuleExprsIter {
- fn new(rule: Rc<Rule>) -> Self {
- let iter =
- try_alloc!(unsafe { sys::nftnl_expr_iter_create(rule.rule as *const sys::nftnl_rule) });
- RuleExprsIter { rule, iter }
- }
-}
-
-impl Iterator for RuleExprsIter {
- type Item = ExpressionWrapper;
-
- fn next(&mut self) -> Option<Self::Item> {
- let next = unsafe { sys::nftnl_expr_iter_next(self.iter) };
- if next.is_null() {
- trace!("RulesExprsIter iterator ending");
- None
- } else {
- trace!("RulesExprsIter returning new expression");
- Some(ExpressionWrapper {
- expr: next,
- rule: self.rule.clone(),
- })
- }
- }
-}
-
-impl Drop for RuleExprsIter {
- fn drop(&mut self) {
- unsafe { sys::nftnl_expr_iter_destroy(self.iter) };
- }
-}
-*/
+impl_nfnetlinkattribute!(inline : Rule, [
+ (sys::NFTA_RULE_TABLE, table),
+ (sys::NFTA_RULE_CHAIN, chain),
+ (sys::NFTA_RULE_HANDLE, handle),
+ (sys::NFTA_RULE_EXPRESSIONS, expressions),
+ (sys::NFTA_RULE_POSITION, position),
+ (
+ sys::NFTA_RULE_USERDATA,
+ userdata
+ ),
+ (sys::NFTA_RULE_ID, id)
+]);
pub fn list_rules_for_chain(chain: &Chain) -> Result<Vec<Rule>, crate::query::Error> {
let mut result = Vec::new();
@@ -338,7 +249,7 @@ pub fn list_rules_for_chain(chain: &Chain) -> Result<Vec<Rule>, crate::query::Er
Ok(())
},
// only retrieve rules from the currently targetted chain
- Some(&Rule::new(chain)?.raw_attributes()),
+ Some(&Rule::new(chain)?),
&mut result,
)?;
Ok(result)
diff --git a/src/table.rs b/src/table.rs
index 5074ac9..96a4964 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -1,62 +1,33 @@
use std::convert::TryFrom;
use std::fmt::Debug;
-use crate::nlmsg::{
- NfNetlinkAttributes, NfNetlinkDeserializable, NfNetlinkObject, NfNetlinkWriter,
-};
-use crate::parser::{parse_object, DecodeError, InnerFormat};
+use crate::nlmsg::{NfNetlinkAttribute, NfNetlinkDeserializable, NfNetlinkObject, NfNetlinkWriter};
+use crate::parser::Parsable;
+use crate::parser::{DecodeError, InnerFormat};
use crate::sys::{
- self, NFNL_SUBSYS_NFTABLES, NFTA_OBJ_TABLE, NFTA_TABLE_FLAGS, NFTA_TABLE_NAME,
- NFT_MSG_DELTABLE, NFT_MSG_GETTABLE, NFT_MSG_NEWTABLE, NLM_F_ACK, NLM_F_CREATE,
+ self, NFT_MSG_DELTABLE, NFT_MSG_GETTABLE, NFT_MSG_NEWTABLE, NLM_F_ACK, NLM_F_CREATE,
};
-use crate::{impl_attr_getters_and_setters, MsgType, ProtocolFamily};
+use crate::{impl_attr_getters_and_setters, impl_nfnetlinkattribute, MsgType, ProtocolFamily};
/// Abstraction of a `nftnl_table`, the top level container in netfilter. A table has a protocol
/// family and contains [`Chain`]s that in turn hold the rules.
///
/// [`Chain`]: struct.Chain.html
-#[derive(PartialEq, Eq)]
+#[derive(Default, PartialEq, Eq)]
pub struct Table {
- inner: NfNetlinkAttributes,
- family: ProtocolFamily,
+ flags: Option<u32>,
+ name: Option<String>,
+ userdata: Option<Vec<u8>>,
+ pub family: ProtocolFamily,
}
impl Table {
pub fn new(family: ProtocolFamily) -> Table {
- Table {
- inner: NfNetlinkAttributes::new(),
- family,
- }
- }
-
- pub fn get_family(&self) -> ProtocolFamily {
- self.family
- }
-
- /*
- /// Returns a textual description of the table.
- pub fn get_str(&self) -> CString {
- let mut descr_buf = vec![0i8; 4096];
- unsafe {
- sys::nftnl_table_snprintf(
- descr_buf.as_mut_ptr() as *mut c_char,
- (descr_buf.len() - 1) as u64,
- self.table,
- sys::NFTNL_OUTPUT_DEFAULT,
- 0,
- );
- CStr::from_ptr(descr_buf.as_ptr() as *mut c_char).to_owned()
- }
+ let mut res = Self::default();
+ res.family = family;
+ res
}
- */
}
-/*
-impl PartialEq for Table {
- fn eq(&self, other: &Self) -> bool {
- self.get_name() == other.get_name() && self.family == other.family
- }
-}
-*/
impl Debug for Table {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -83,42 +54,49 @@ impl NfNetlinkObject for Table {
seq,
None,
);
- self.inner.serialize(writer);
+ let buf = writer.add_data_zeroed(self.get_size());
+ unsafe {
+ self.write_payload(buf.as_mut_ptr());
+ }
writer.finalize_writing_object();
}
}
impl NfNetlinkDeserializable for Table {
fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
- let (inner, nfgenmsg, remaining_data) =
- parse_object::<Self>(buf, NFT_MSG_NEWTABLE, NFT_MSG_DELTABLE)?;
+ let (mut obj, nfgenmsg, remaining_data) =
+ Self::parse_object(buf, NFT_MSG_NEWTABLE, NFT_MSG_DELTABLE)?;
+ obj.family = ProtocolFamily::try_from(nfgenmsg.nfgen_family as i32)?;
- Ok((
- Self {
- inner,
- family: ProtocolFamily::try_from(nfgenmsg.nfgen_family as i32)?,
- },
- remaining_data,
- ))
+ Ok((obj, remaining_data))
}
}
impl_attr_getters_and_setters!(
Table,
[
- (get_flags, set_flags, with_flags, sys::NFTA_TABLE_FLAGS, U32, u32),
- (get_name, set_name, with_name, sys::NFTA_TABLE_NAME, String, String),
+ (get_name, set_name, with_name, sys::NFTA_TABLE_NAME, name, String),
+ (get_flags, set_flags, with_flags, sys::NFTA_TABLE_FLAGS, flags, u32),
(
get_userdata,
set_userdata,
with_userdata,
sys::NFTA_TABLE_USERDATA,
- VecU8,
+ userdata,
Vec<u8>
)
]
);
+impl_nfnetlinkattribute!(
+ inline : Table,
+ [
+ (sys::NFTA_TABLE_NAME, name),
+ (sys::NFTA_TABLE_FLAGS, flags),
+ (sys::NFTA_TABLE_USERDATA, userdata)
+ ]
+);
+
pub fn list_tables() -> Result<Vec<Table>, crate::query::Error> {
let mut result = Vec::new();
crate::query::list_objects_with_data(