aboutsummaryrefslogtreecommitdiff
path: root/rustables/src/rule.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rustables/src/rule.rs')
-rw-r--r--rustables/src/rule.rs132
1 files changed, 125 insertions, 7 deletions
diff --git a/rustables/src/rule.rs b/rustables/src/rule.rs
index 6e15db7..b315daf 100644
--- a/rustables/src/rule.rs
+++ b/rustables/src/rule.rs
@@ -1,3 +1,4 @@
+use crate::expr::ExpressionWrapper;
use crate::{chain::Chain, expr::Expression, MsgType};
use rustables_sys::{self as sys, libc};
use std::ffi::{c_void, CStr, CString};
@@ -7,8 +8,8 @@ use std::rc::Rc;
/// A nftables firewall rule.
pub struct Rule {
- rule: *mut sys::nftnl_rule,
- chain: Rc<Chain>,
+ pub(crate) rule: *mut sys::nftnl_rule,
+ pub(crate) chain: Rc<Chain>,
}
impl Rule {
@@ -82,14 +83,15 @@ impl Rule {
pub fn get_userdata(&self) -> Option<&CStr> {
unsafe {
let ptr = sys::nftnl_rule_get_str(self.rule, sys::NFTNL_RULE_USERDATA as u16);
- if ptr == std::ptr::null() {
- return None;
+ if !ptr.is_null() {
+ Some(CStr::from_ptr(ptr))
+ } else {
+ None
}
- Some(CStr::from_ptr(ptr))
}
}
- /// Update the userdata of this chain.
+ /// Updates the userdata of this chain.
pub fn set_userdata(&self, data: &CStr) {
unsafe {
sys::nftnl_rule_set_str(self.rule, sys::NFTNL_RULE_USERDATA as u16, data.as_ptr());
@@ -111,6 +113,11 @@ impl Rule {
}
}
+ /// Retrieves an iterator to loop over the expressions of the rule
+ pub fn get_exprs(self: &Rc<Self>) -> RuleExprsIter {
+ RuleExprsIter::new(self.clone())
+ }
+
#[cfg(feature = "unsafe-raw-handles")]
/// Returns the raw handle.
pub fn as_ptr(&self) -> *const sys::nftnl_rule {
@@ -122,6 +129,59 @@ impl Rule {
pub fn as_mut_ptr(&mut self) -> *mut sys::nftnl_rule {
self.rule
}
+
+ /// Perform a deep comparizon of rules, by checking they have the same expressions inside.
+ /// This is not enabled by default in our PartialEq implementation because of the
+ /// difficulty to compare an expression generated by the library with the expressions returned
+ /// by the kernel when iterating over the currently in-use rules. The kernel-returned
+ /// expressions may have additional attributes despite being generated from the same rule.
+ /// This is particularly true for the 'nat' expression).
+ pub fn deep_eq(&self, other: &Self) -> bool {
+ if self != other {
+ return false;
+ }
+
+ let self_exprs =
+ try_alloc!(unsafe { sys::nftnl_expr_iter_create(self.rule as *const sys::nftnl_rule) });
+ let other_exprs = try_alloc!(unsafe {
+ sys::nftnl_expr_iter_create(other.rule as *const sys::nftnl_rule)
+ });
+
+ loop {
+ let self_next = unsafe { sys::nftnl_expr_iter_next(self_exprs) };
+ let other_next = unsafe { sys::nftnl_expr_iter_next(other_exprs) };
+ if self_next.is_null() && other_next.is_null() {
+ return true;
+ } else if self_next.is_null() || other_next.is_null() {
+ return false;
+ }
+
+ // we are falling back on comparing the strings, because there is no easy mechanism to
+ // perform a memcmp() between the two expressions :/
+ let mut self_str = [0; 256];
+ let mut other_str = [0; 256];
+ unsafe {
+ sys::nftnl_expr_snprintf(
+ self_str.as_mut_ptr(),
+ (self_str.len() - 1) as u64,
+ self_next,
+ sys::NFTNL_OUTPUT_DEFAULT,
+ 0,
+ );
+ sys::nftnl_expr_snprintf(
+ other_str.as_mut_ptr(),
+ (other_str.len() - 1) as u64,
+ other_next,
+ sys::NFTNL_OUTPUT_DEFAULT,
+ 0,
+ );
+ }
+
+ if self_str != other_str {
+ return false;
+ }
+ }
+ }
}
impl Debug for Rule {
@@ -132,7 +192,28 @@ impl Debug for Rule {
impl PartialEq for Rule {
fn eq(&self, other: &Self) -> bool {
- self.get_chain() == other.get_chain() && self.get_handle() == other.get_handle()
+ 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;
}
}
@@ -163,6 +244,43 @@ impl Drop for 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) };
+ }
+}
+
#[cfg(feature = "query")]
pub fn get_rules_cb(
header: &libc::nlmsghdr,