aboutsummaryrefslogtreecommitdiff
path: root/rustables/src/expr/cmp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rustables/src/expr/cmp.rs')
-rw-r--r--rustables/src/expr/cmp.rs49
1 files changed, 47 insertions, 2 deletions
diff --git a/rustables/src/expr/cmp.rs b/rustables/src/expr/cmp.rs
index b14aa1d..e4cfb0f 100644
--- a/rustables/src/expr/cmp.rs
+++ b/rustables/src/expr/cmp.rs
@@ -9,7 +9,7 @@ use std::{
};
/// Comparison operator.
-#[derive(Copy, Clone, Eq, PartialEq)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum CmpOp {
/// Equals.
Eq,
@@ -38,9 +38,23 @@ impl CmpOp {
Gte => libc::NFT_CMP_GTE as u32,
}
}
+
+ pub fn from_raw(val: u32) -> Option<Self> {
+ use self::CmpOp::*;
+ match val as i32 {
+ libc::NFT_CMP_EQ => Some(Eq),
+ libc::NFT_CMP_NEQ => Some(Neq),
+ libc::NFT_CMP_LT => Some(Lt),
+ libc::NFT_CMP_LTE => Some(Lte),
+ libc::NFT_CMP_GT => Some(Gt),
+ libc::NFT_CMP_GTE => Some(Gte),
+ _ => None,
+ }
+ }
}
/// Comparator expression. Allows comparing the content of the netfilter register with any value.
+#[derive(Debug, PartialEq)]
pub struct Cmp<T: ToSlice> {
op: CmpOp,
data: T,
@@ -54,11 +68,42 @@ impl<T: ToSlice> Cmp<T> {
}
}
-impl<T: ToSlice> Expression for Cmp<T> {
+impl<T: ToSlice + Copy> Expression for Cmp<T> {
fn get_raw_name() -> *const c_char {
b"cmp\0" as *const _ as *const c_char
}
+ fn from_expr(expr: *const sys::nftnl_expr) -> Option<Self>
+ where
+ Self: Sized,
+ {
+ unsafe {
+ let ref_len = std::mem::size_of::<T>() as u32;
+ let mut data_len = 0;
+ let data = sys::nftnl_expr_get(
+ expr,
+ sys::NFTNL_EXPR_CMP_DATA as u16,
+ &mut data_len as *mut u32,
+ );
+
+ if data.is_null() {
+ return None;
+ } else if data_len != ref_len {
+ debug!("Invalid size requested for deserializing a 'cmp' expression: expected {} bytes, got {}", ref_len, data_len);
+ return None;
+ }
+
+ // Warning: this is *very* dangerous safety wise if the user supply us with
+ // a type that have the same size as T but a different memory layout.
+ // Is there a better way? And if there isn't, shouldn't we gate this behind
+ // an "unsafe" boundary?
+ let data = *(data as *const T);
+
+ let op = CmpOp::from_raw(sys::nftnl_expr_get_u32(expr, sys::NFTNL_EXPR_CMP_OP as u16));
+ op.map(|op| Cmp { op, data })
+ }
+ }
+
fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr {
unsafe {
let expr = try_alloc!(sys::nftnl_expr_alloc(Self::get_raw_name()));