aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/expr/ct.rs106
-rw-r--r--src/expr/mod.rs5
-rw-r--r--src/expr/nat.rs63
-rw-r--r--src/expr/payload.rs3
-rw-r--r--src/parser.rs3
-rw-r--r--tests/expr.rs187
6 files changed, 144 insertions, 223 deletions
diff --git a/src/expr/ct.rs b/src/expr/ct.rs
index 7d6614c..ccf61e1 100644
--- a/src/expr/ct.rs
+++ b/src/expr/ct.rs
@@ -1,9 +1,13 @@
-use super::{DeserializationError, Expression, Rule};
-use crate::sys::{self, libc};
-use std::os::raw::c_char;
+use rustables_macros::{nfnetlink_enum, nfnetlink_struct};
+
+use crate::sys::{
+ NFTA_CT_DIRECTION, NFTA_CT_DREG, NFTA_CT_KEY, NFTA_CT_SREG, NFT_CT_MARK, NFT_CT_STATE,
+};
+
+use super::{Expression, Register};
bitflags::bitflags! {
- pub struct States: u32 {
+ pub struct ConnTrackState: u32 {
const INVALID = 1;
const ESTABLISHED = 2;
const RELATED = 4;
@@ -12,76 +16,50 @@ bitflags::bitflags! {
}
}
-pub enum Conntrack {
- State,
- Mark { set: bool },
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[nfnetlink_enum(u32, nested = true)]
+pub enum ConntrackKey {
+ State = NFT_CT_STATE,
+ Mark = NFT_CT_MARK,
}
-impl Conntrack {
- fn raw_key(&self) -> u32 {
- match *self {
- Conntrack::State => libc::NFT_CT_STATE as u32,
- Conntrack::Mark { .. } => libc::NFT_CT_MARK as u32,
- }
- }
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+#[nfnetlink_struct(nested = true)]
+pub struct Conntrack {
+ #[field(NFTA_CT_DREG)]
+ pub dreg: Register,
+ #[field(NFTA_CT_KEY)]
+ pub key: ConntrackKey,
+ #[field(NFTA_CT_DIRECTION)]
+ pub direction: u8,
+ #[field(NFTA_CT_SREG)]
+ pub sreg: Register,
}
impl Expression for Conntrack {
- fn get_raw_name() -> *const c_char {
- b"ct\0" as *const _ as *const c_char
+ fn get_name() -> &'static str {
+ "ct"
}
+}
- fn from_expr(expr: *const sys::nftnl_expr) -> Result<Self, DeserializationError>
- where
- Self: Sized,
- {
- unsafe {
- let ct_key = sys::nftnl_expr_get_u32(expr, sys::NFTNL_EXPR_CT_KEY as u16);
- let ct_sreg_is_set = sys::nftnl_expr_is_set(expr, sys::NFTNL_EXPR_CT_SREG as u16);
-
- match ct_key as i32 {
- libc::NFT_CT_STATE => Ok(Conntrack::State),
- libc::NFT_CT_MARK => Ok(Conntrack::Mark {
- set: ct_sreg_is_set,
- }),
- _ => Err(DeserializationError::InvalidValue),
- }
- }
+impl Conntrack {
+ pub fn set_mark_value(&mut self, reg: Register) {
+ self.set_sreg(reg);
+ self.set_key(ConntrackKey::Mark);
}
- fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr {
- unsafe {
- let expr = try_alloc!(sys::nftnl_expr_alloc(Self::get_raw_name()));
-
- if let Conntrack::Mark { set: true } = self {
- sys::nftnl_expr_set_u32(
- expr,
- sys::NFTNL_EXPR_CT_SREG as u16,
- libc::NFT_REG_1 as u32,
- );
- } else {
- sys::nftnl_expr_set_u32(
- expr,
- sys::NFTNL_EXPR_CT_DREG as u16,
- libc::NFT_REG_1 as u32,
- );
- }
- sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_CT_KEY as u16, self.raw_key());
+ pub fn with_mark_value(mut self, reg: Register) -> Self {
+ self.set_mark_value(reg);
+ self
+ }
- expr
- }
+ pub fn retrieve_value(&mut self, key: ConntrackKey) {
+ self.set_key(key);
+ self.set_dreg(Register::Reg1);
}
-}
-#[macro_export]
-macro_rules! nft_expr_ct {
- (state) => {
- $crate::expr::Conntrack::State
- };
- (mark set) => {
- $crate::expr::Conntrack::Mark { set: true }
- };
- (mark) => {
- $crate::expr::Conntrack::Mark { set: false }
- };
+ pub fn with_retrieve_value(mut self, key: ConntrackKey) -> Self {
+ self.retrieve_value(key);
+ self
+ }
}
diff --git a/src/expr/mod.rs b/src/expr/mod.rs
index 0a7f54c..a6da2cd 100644
--- a/src/expr/mod.rs
+++ b/src/expr/mod.rs
@@ -27,11 +27,9 @@ pub use self::cmp::*;
mod counter;
pub use self::counter::*;
-/*
pub mod ct;
pub use self::ct::*;
-*/
mod immediate;
pub use self::immediate::*;
@@ -224,7 +222,8 @@ create_expr_variant!(
[Counter, Counter],
[Nat, Nat],
[Payload, Payload],
- [Cmp, Cmp]
+ [Cmp, Cmp],
+ [Conntrack, Conntrack]
);
#[derive(Debug, Clone, PartialEq, Eq, Default)]
diff --git a/src/expr/nat.rs b/src/expr/nat.rs
index 8fb73fa..406b2e6 100644
--- a/src/expr/nat.rs
+++ b/src/expr/nat.rs
@@ -35,66 +35,3 @@ impl Expression for Nat {
"nat"
}
}
-/*
-
- fn from_expr(expr: *const sys::nftnl_expr) -> Result<Self, DeserializationError>
- where
- Self: Sized,
- {
- unsafe {
- let nat_type = NatType::from_raw(sys::nftnl_expr_get_u32(
- expr,
- sys::NFTNL_EXPR_NAT_TYPE as u16,
- ))?;
-
- let family = ProtoFamily::try_from(sys::nftnl_expr_get_u32(
- expr,
- sys::NFTNL_EXPR_NAT_FAMILY as u16,
- ) as i32)?;
-
- let ip_register = Register::from_raw(sys::nftnl_expr_get_u32(
- expr,
- sys::NFTNL_EXPR_NAT_REG_ADDR_MIN as u16,
- ))?;
-
- let mut port_register = None;
- if sys::nftnl_expr_is_set(expr, sys::NFTNL_EXPR_NAT_REG_PROTO_MIN as u16) {
- port_register = Some(Register::from_raw(sys::nftnl_expr_get_u32(
- expr,
- sys::NFTNL_EXPR_NAT_REG_PROTO_MIN as u16,
- ))?);
- }
-
- Ok(Nat {
- ip_register,
- nat_type,
- family,
- port_register,
- })
- }
- }
-
- fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr {
- let expr = try_alloc!(unsafe { sys::nftnl_expr_alloc(Self::get_raw_name()) });
-
- unsafe {
- sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_NAT_TYPE as u16, self.nat_type as u32);
- sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_NAT_FAMILY as u16, self.family as u32);
- sys::nftnl_expr_set_u32(
- expr,
- sys::NFTNL_EXPR_NAT_REG_ADDR_MIN as u16,
- self.ip_register.to_raw(),
- );
- if let Some(port_register) = self.port_register {
- sys::nftnl_expr_set_u32(
- expr,
- sys::NFTNL_EXPR_NAT_REG_PROTO_MIN as u16,
- port_register.to_raw(),
- );
- }
- }
-
- expr
- }
-}
-*/
diff --git a/src/expr/payload.rs b/src/expr/payload.rs
index f1cd468..490a4ec 100644
--- a/src/expr/payload.rs
+++ b/src/expr/payload.rs
@@ -2,7 +2,6 @@ use rustables_macros::nfnetlink_struct;
use super::{Expression, Register};
use crate::{
- nlmsg::{NfNetlinkAttribute, NfNetlinkDeserializable},
parser::DecodeError,
sys::{self, NFT_PAYLOAD_LL_HEADER, NFT_PAYLOAD_NETWORK_HEADER, NFT_PAYLOAD_TRANSPORT_HEADER},
};
@@ -66,7 +65,7 @@ pub enum PayloadType {
}
impl PayloadType {
- fn parse_from_payload(raw: &Payload) -> Result<Self, DecodeError> {
+ pub fn parse_from_payload(raw: &Payload) -> Result<Self, DecodeError> {
if raw.base.is_none() {
return Err(DecodeError::PayloadMissingBase);
}
diff --git a/src/parser.rs b/src/parser.rs
index b5e9f18..c402dae 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -85,6 +85,9 @@ pub enum DecodeError {
#[error("Invalid type for a compare expression")]
UnknownCmpOp(u32),
+ #[error("Invalid type for a conntrack key")]
+ UnknownConntrackKey(u32),
+
#[error("Unsupported value for a link layer header field")]
UnknownLinkLayerHeaderField(u32, u32),
diff --git a/tests/expr.rs b/tests/expr.rs
index 3b71c12..4367116 100644
--- a/tests/expr.rs
+++ b/tests/expr.rs
@@ -1,19 +1,20 @@
use rustables::{
expr::{
- Bitwise, Cmp, CmpOp, ExpressionList, HeaderField, HighLevelPayload, IcmpCode, Immediate,
- Log, Meta, MetaType, Nat, NatType, Register, Reject, RejectType, TCPHeaderField,
- TransportHeaderField, VerdictKind,
+ Bitwise, Cmp, CmpOp, Conntrack, ConntrackKey, Counter, ExpressionList, HeaderField,
+ HighLevelPayload, IcmpCode, Immediate, Log, Meta, MetaType, Nat, NatType, Register, Reject,
+ RejectType, TCPHeaderField, TransportHeaderField, VerdictKind,
},
sys::{
NFTA_BITWISE_DREG, NFTA_BITWISE_LEN, NFTA_BITWISE_MASK, NFTA_BITWISE_SREG,
- NFTA_BITWISE_XOR, NFTA_CMP_DATA, NFTA_CMP_OP, NFTA_CMP_SREG, NFTA_DATA_VALUE,
- NFTA_DATA_VERDICT, NFTA_EXPR_DATA, NFTA_EXPR_NAME, NFTA_IMMEDIATE_DATA,
- NFTA_IMMEDIATE_DREG, NFTA_LIST_ELEM, NFTA_LOG_GROUP, NFTA_LOG_PREFIX, NFTA_META_DREG,
- NFTA_META_KEY, NFTA_NAT_FAMILY, NFTA_NAT_REG_ADDR_MIN, NFTA_NAT_TYPE, NFTA_PAYLOAD_BASE,
- NFTA_PAYLOAD_DREG, NFTA_PAYLOAD_LEN, NFTA_PAYLOAD_OFFSET, NFTA_REJECT_ICMP_CODE,
- NFTA_REJECT_TYPE, NFTA_RULE_CHAIN, NFTA_RULE_EXPRESSIONS, NFTA_RULE_TABLE,
- NFTA_VERDICT_CODE, NFT_CMP_EQ, NFT_META_PROTOCOL, NFT_NAT_SNAT,
- NFT_PAYLOAD_TRANSPORT_HEADER, NFT_REG_1, NFT_REG_VERDICT, NFT_REJECT_ICMPX_UNREACH,
+ NFTA_BITWISE_XOR, NFTA_CMP_DATA, NFTA_CMP_OP, NFTA_CMP_SREG, NFTA_COUNTER_BYTES,
+ NFTA_COUNTER_PACKETS, NFTA_CT_DREG, NFTA_CT_KEY, NFTA_DATA_VALUE, NFTA_DATA_VERDICT,
+ NFTA_EXPR_DATA, NFTA_EXPR_NAME, NFTA_IMMEDIATE_DATA, NFTA_IMMEDIATE_DREG, NFTA_LIST_ELEM,
+ NFTA_LOG_GROUP, NFTA_LOG_PREFIX, NFTA_META_DREG, NFTA_META_KEY, NFTA_NAT_FAMILY,
+ NFTA_NAT_REG_ADDR_MIN, NFTA_NAT_TYPE, NFTA_PAYLOAD_BASE, NFTA_PAYLOAD_DREG,
+ NFTA_PAYLOAD_LEN, NFTA_PAYLOAD_OFFSET, NFTA_REJECT_ICMP_CODE, NFTA_REJECT_TYPE,
+ NFTA_RULE_CHAIN, NFTA_RULE_EXPRESSIONS, NFTA_RULE_TABLE, NFTA_VERDICT_CODE, NFT_CMP_EQ,
+ NFT_CT_STATE, NFT_META_PROTOCOL, NFT_NAT_SNAT, NFT_PAYLOAD_TRANSPORT_HEADER, NFT_REG_1,
+ NFT_REG_VERDICT, NFT_REJECT_ICMPX_UNREACH,
},
ProtocolFamily,
};
@@ -132,86 +133,90 @@ fn cmp_expr_is_valid() {
);
}
-//#[test]
-//fn counter_expr_is_valid() {
-// let nb_bytes = 123456u64;
-// let nb_packets = 987u64;
-// let mut counter = Counter::new();
-// counter.nb_bytes = nb_bytes;
-// counter.nb_packets = nb_packets;
-//
-// let mut rule = get_test_rule();
-// let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &counter);
-// assert_eq!(nlmsghdr.nlmsg_len, 100);
-//
-// assert_eq!(
-// raw_expr,
-// NetlinkExpr::List(vec![
-// NetlinkExpr::Final(NFTA_RULE_TABLE, TABLE_NAME.to_vec()),
-// NetlinkExpr::Final(NFTA_RULE_CHAIN, CHAIN_NAME.to_vec()),
-// NetlinkExpr::Nested(
-// NFTA_RULE_EXPRESSIONS,
-// vec![NetlinkExpr::Nested(
-// NFTA_LIST_ELEM,
-// vec![
-// NetlinkExpr::Final(NFTA_EXPR_NAME, b"counter\0".to_vec()),
-// NetlinkExpr::Nested(
-// NFTA_EXPR_DATA,
-// vec![
-// NetlinkExpr::Final(
-// NFTA_COUNTER_BYTES,
-// nb_bytes.to_be_bytes().to_vec()
-// ),
-// NetlinkExpr::Final(
-// NFTA_COUNTER_PACKETS,
-// nb_packets.to_be_bytes().to_vec()
-// )
-// ]
-// )
-// ]
-// )]
-// )
-// ])
-// .to_raw()
-// );
-//}
-//
-//#[test]
-//fn ct_expr_is_valid() {
-// let ct = Conntrack::State;
-// let mut rule = get_test_rule();
-// let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &ct);
-// assert_eq!(nlmsghdr.nlmsg_len, 88);
-//
-// assert_eq!(
-// raw_expr,
-// NetlinkExpr::List(vec![
-// NetlinkExpr::Final(NFTA_RULE_TABLE, TABLE_NAME.to_vec()),
-// NetlinkExpr::Final(NFTA_RULE_CHAIN, CHAIN_NAME.to_vec()),
-// NetlinkExpr::Nested(
-// NFTA_RULE_EXPRESSIONS,
-// vec![NetlinkExpr::Nested(
-// NFTA_LIST_ELEM,
-// vec![
-// NetlinkExpr::Final(NFTA_EXPR_NAME, b"ct\0".to_vec()),
-// NetlinkExpr::Nested(
-// NFTA_EXPR_DATA,
-// vec![
-// NetlinkExpr::Final(
-// NFTA_CT_KEY,
-// NFT_CT_STATE.to_be_bytes().to_vec()
-// ),
-// NetlinkExpr::Final(NFTA_CT_DREG, NFT_REG_1.to_be_bytes().to_vec())
-// ]
-// )
-// ]
-// )]
-// )
-// ])
-// .to_raw()
-// )
-//}
-//
+#[test]
+fn counter_expr_is_valid() {
+ let nb_bytes = 123456u64;
+ let nb_packets = 987u64;
+ let counter = Counter::default()
+ .with_nb_bytes(nb_bytes)
+ .with_nb_packets(nb_packets);
+
+ let mut rule = get_test_rule().with_expressions(vec![counter]);
+
+ let mut buf = Vec::new();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg(&mut buf, &mut rule);
+ assert_eq!(nlmsghdr.nlmsg_len, 100);
+
+ assert_eq!(
+ raw_expr,
+ NetlinkExpr::List(vec![
+ NetlinkExpr::Final(NFTA_RULE_TABLE, TABLE_NAME.as_bytes().to_vec()),
+ NetlinkExpr::Final(NFTA_RULE_CHAIN, CHAIN_NAME.as_bytes().to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_RULE_EXPRESSIONS,
+ vec![NetlinkExpr::Nested(
+ NFTA_LIST_ELEM,
+ vec![
+ NetlinkExpr::Final(NFTA_EXPR_NAME, b"counter".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_COUNTER_BYTES,
+ nb_bytes.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_COUNTER_PACKETS,
+ nb_packets.to_be_bytes().to_vec()
+ )
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[test]
+fn ct_expr_is_valid() {
+ let ct = Conntrack::default().with_retrieve_value(ConntrackKey::State);
+ let mut rule = get_test_rule().with_expressions(vec![ct]);
+
+ let mut buf = Vec::new();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg(&mut buf, &mut rule);
+ assert_eq!(nlmsghdr.nlmsg_len, 88);
+
+ assert_eq!(
+ raw_expr,
+ NetlinkExpr::List(vec![
+ NetlinkExpr::Final(NFTA_RULE_TABLE, TABLE_NAME.as_bytes().to_vec()),
+ NetlinkExpr::Final(NFTA_RULE_CHAIN, CHAIN_NAME.as_bytes().to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_RULE_EXPRESSIONS,
+ vec![NetlinkExpr::Nested(
+ NFTA_LIST_ELEM,
+ vec![
+ NetlinkExpr::Final(NFTA_EXPR_NAME, b"ct".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_CT_KEY,
+ NFT_CT_STATE.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(NFTA_CT_DREG, NFT_REG_1.to_be_bytes().to_vec())
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ )
+}
+
#[test]
fn immediate_expr_is_valid() {
let immediate = Immediate::new_data(vec![42u8], Register::Reg1);