diff options
author | Simon THOBY <git@nightmared.fr> | 2021-10-27 19:58:53 +0200 |
---|---|---|
committer | Simon THOBY <git@nightmared.fr> | 2021-11-02 22:18:12 +0100 |
commit | 45b71ba1da0a88278d126d5e154ed8ca90e57892 (patch) | |
tree | 3b079b03758e99e7836bed4b867d33072761a861 /rustables/src | |
parent | 0156ef5a8b0bdc8e07b8ac12e4c99d5047f1c9cc (diff) |
provide a (deficient) method for a deep comparison of rules
Diffstat (limited to 'rustables/src')
-rw-r--r-- | rustables/src/rule.rs | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/rustables/src/rule.rs b/rustables/src/rule.rs index fcacf6a..b315daf 100644 --- a/rustables/src/rule.rs +++ b/rustables/src/rule.rs @@ -129,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 { @@ -139,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; } } |