diff options
Diffstat (limited to 'rustables/src/expr/immediate.rs')
-rw-r--r-- | rustables/src/expr/immediate.rs | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/rustables/src/expr/immediate.rs b/rustables/src/expr/immediate.rs index 15eb452..e8823b1 100644 --- a/rustables/src/expr/immediate.rs +++ b/rustables/src/expr/immediate.rs @@ -18,11 +18,47 @@ impl<T> Immediate<T> { } } -impl<T> Expression for Immediate<T> { +// The Copy requirement is present to allow us to dereference the newly created raw pointer in `from_expr` +impl<T: Copy> Expression for Immediate<T> { fn get_raw_name() -> *const c_char { b"immediate\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_IMM_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 an 'immediate' 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 register = Register::from_raw(sys::nftnl_expr_get_u32( + expr, + sys::NFTNL_EXPR_IMM_DREG as u16, + )); + + register.map(|register| Immediate { data, register }) + } + } + fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { unsafe { let expr = try_alloc!(sys::nftnl_expr_alloc(Self::get_raw_name())); |