aboutsummaryrefslogtreecommitdiff
path: root/rustables/src/expr/mod.rs
diff options
context:
space:
mode:
authorSimon THOBY <git@nightmared.fr>2021-11-05 06:23:45 +0000
committerSimon THOBY <git@nightmared.fr>2021-11-05 06:23:45 +0000
commit46b22d88c36863851e4b27efa767d28c8aeecfe0 (patch)
treeab1a638de7587e7b73fe64093428218e1c545004 /rustables/src/expr/mod.rs
parent3f61ea42bd291c208d07006d8019c25d588f9183 (diff)
parent1bec5a5c30541e47e9c7cff839ac0e7dd3fb6215 (diff)
Merge branch 'manipulate-exprs' into 'master'
Add functions to iterate over the expressions of existing rules See merge request rustwall/rustables!3
Diffstat (limited to 'rustables/src/expr/mod.rs')
-rw-r--r--rustables/src/expr/mod.rs170
1 files changed, 145 insertions, 25 deletions
diff --git a/rustables/src/expr/mod.rs b/rustables/src/expr/mod.rs
index 99ea44b..b20a752 100644
--- a/rustables/src/expr/mod.rs
+++ b/rustables/src/expr/mod.rs
@@ -3,32 +3,14 @@
//!
//! [`Rule`]: struct.Rule.html
+use std::borrow::Cow;
+use std::net::IpAddr;
+use std::net::Ipv4Addr;
+use std::net::Ipv6Addr;
+
use super::rule::Rule;
use rustables_sys::{self as sys, libc};
-
-/// Trait for every safe wrapper of an nftables expression.
-pub trait Expression {
- /// Allocates and returns the low level `nftnl_expr` representation of this expression.
- /// The caller to this method is responsible for freeing the expression.
- fn to_expr(&self, rule: &Rule) -> *mut sys::nftnl_expr;
-}
-
-/// A netfilter data register. The expressions store and read data to and from these
-/// when evaluating rule statements.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-#[repr(i32)]
-pub enum Register {
- Reg1 = libc::NFT_REG_1,
- Reg2 = libc::NFT_REG_2,
- Reg3 = libc::NFT_REG_3,
- Reg4 = libc::NFT_REG_4,
-}
-
-impl Register {
- pub fn to_raw(self) -> u32 {
- self as u32
- }
-}
+use thiserror::Error;
mod bitwise;
pub use self::bitwise::*;
@@ -63,9 +45,147 @@ pub use self::nat::*;
mod payload;
pub use self::payload::*;
+mod reject;
+pub use self::reject::{IcmpCode, Reject};
+
+mod register;
+pub use self::register::Register;
+
mod verdict;
pub use self::verdict::*;
+mod wrapper;
+pub use self::wrapper::ExpressionWrapper;
+
+#[derive(Debug, Error)]
+pub enum DeserializationError {
+ #[error("The expected expression type doesn't match the name of the raw expression")]
+ /// The expected expression type doesn't match the name of the raw expression
+ InvalidExpressionKind,
+
+ #[error("Deserializing the requested type isn't implemented yet")]
+ /// Deserializing the requested type isn't implemented yet
+ NotImplemented,
+
+ #[error("The expression value cannot be deserialized to the requested type")]
+ /// The expression value cannot be deserialized to the requested type
+ InvalidValue,
+
+ #[error("A pointer was null while a non-null pointer was expected")]
+ /// A pointer was null while a non-null pointer was expected
+ NullPointer,
+
+ #[error(
+ "The size of a raw value was incoherent with the expected type of the deserialized value"
+ )]
+ /// The size of a raw value was incoherent with the expected type of the deserialized value
+ InvalidDataSize,
+
+ #[error(transparent)]
+ /// Couldn't find a matching protocol
+ InvalidProtolFamily(#[from] super::InvalidProtocolFamily),
+}
+
+/// Trait for every safe wrapper of an nftables expression.
+pub trait Expression {
+ /// Returns the raw name used by nftables to identify the rule.
+ fn get_raw_name() -> *const libc::c_char;
+
+ /// Try to parse the expression from a raw nftables expression,
+ /// returning a [DeserializationError] if the attempted parsing failed.
+ fn from_expr(_expr: *const sys::nftnl_expr) -> Result<Self, DeserializationError>
+ where
+ Self: Sized,
+ {
+ Err(DeserializationError::NotImplemented)
+ }
+
+ /// Allocates and returns the low level `nftnl_expr` representation of this expression.
+ /// The caller to this method is responsible for freeing the expression.
+ fn to_expr(&self, rule: &Rule) -> *mut sys::nftnl_expr;
+}
+
+/// A type that can be converted into a byte buffer.
+pub trait ToSlice {
+ /// Returns the data this type represents.
+ fn to_slice(&self) -> Cow<'_, [u8]>;
+}
+
+impl<'a> ToSlice for &'a [u8] {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ Cow::Borrowed(self)
+ }
+}
+
+impl<'a> ToSlice for &'a [u16] {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ let ptr = self.as_ptr() as *const u8;
+ let len = self.len() * 2;
+ Cow::Borrowed(unsafe { std::slice::from_raw_parts(ptr, len) })
+ }
+}
+
+impl ToSlice for IpAddr {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ match *self {
+ IpAddr::V4(ref addr) => addr.to_slice(),
+ IpAddr::V6(ref addr) => addr.to_slice(),
+ }
+ }
+}
+
+impl ToSlice for Ipv4Addr {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ Cow::Owned(self.octets().to_vec())
+ }
+}
+
+impl ToSlice for Ipv6Addr {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ Cow::Owned(self.octets().to_vec())
+ }
+}
+
+impl ToSlice for u8 {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ Cow::Owned(vec![*self])
+ }
+}
+
+impl ToSlice for u16 {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ let b0 = (*self & 0x00ff) as u8;
+ let b1 = (*self >> 8) as u8;
+ Cow::Owned(vec![b0, b1])
+ }
+}
+
+impl ToSlice for u32 {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ let b0 = *self as u8;
+ let b1 = (*self >> 8) as u8;
+ let b2 = (*self >> 16) as u8;
+ let b3 = (*self >> 24) as u8;
+ Cow::Owned(vec![b0, b1, b2, b3])
+ }
+}
+
+impl ToSlice for i32 {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ let b0 = *self as u8;
+ let b1 = (*self >> 8) as u8;
+ let b2 = (*self >> 16) as u8;
+ let b3 = (*self >> 24) as u8;
+ Cow::Owned(vec![b0, b1, b2, b3])
+ }
+}
+
+impl<'a> ToSlice for &'a str {
+ fn to_slice(&self) -> Cow<'_, [u8]> {
+ Cow::from(self.as_bytes())
+ }
+}
+
#[macro_export(local_inner_macros)]
macro_rules! nft_expr {
(bitwise mask $mask:expr,xor $xor:expr) => {
@@ -75,7 +195,7 @@ macro_rules! nft_expr {
nft_expr_cmp!($op $data)
};
(counter) => {
- $crate::expr::Counter
+ $crate::expr::Counter { nb_bytes: 0, nb_packets: 0}
};
(ct $key:ident set) => {
nft_expr_ct!($key set)