aboutsummaryrefslogtreecommitdiff
path: root/tests/expr.rs
diff options
context:
space:
mode:
authorlafleur <lafleur@boum.org>2021-11-07 14:40:30 +0100
committerlafleur <lafleur@boum.org>2021-11-07 14:40:30 +0100
commit84bf6246af06ec9339ee293faa16797bbee58ceb (patch)
treeee973936607d7ee1b4cd43a484e7d658dfdc182b /tests/expr.rs
parent1e33e3ab0790d977add329e9686b4b9e5570ba3c (diff)
wipe rustables-sys away
Diffstat (limited to 'tests/expr.rs')
-rw-r--r--tests/expr.rs700
1 files changed, 700 insertions, 0 deletions
diff --git a/tests/expr.rs b/tests/expr.rs
new file mode 100644
index 0000000..5c27119
--- /dev/null
+++ b/tests/expr.rs
@@ -0,0 +1,700 @@
+use rustables::{nft_nlmsg_maxsize, Chain, MsgType, NlMsg, ProtoFamily, Rule, Table};
+use rustables::set::Set;
+use rustables::sys::libc::{nlmsghdr, AF_UNIX, NFNETLINK_V0, NFNL_SUBSYS_NFTABLES, NF_DROP};
+use rustables::expr::{
+ Bitwise, Cmp, CmpOp, Conntrack, Counter, Expression, HeaderField, IcmpCode, Immediate, Log,
+ LogGroup, LogPrefix, Lookup, Meta, Nat, NatType, Payload, Register, Reject, TcpHeaderField,
+ TransportHeaderField, Verdict
+};
+use std::ffi::{c_void, CStr};
+use std::mem::size_of;
+use std::net::Ipv4Addr;
+use std::rc::Rc;
+use thiserror::Error;
+
+mod sys;
+use sys::*;
+
+fn get_subsystem_from_nlmsghdr_type(x: u16) -> u8 {
+ ((x & 0xff00) >> 8) as u8
+}
+fn get_operation_from_nlmsghdr_type(x: u16) -> u8 {
+ (x & 0x00ff) as u8
+}
+
+const TABLE_NAME: &[u8; 10] = b"mocktable\0";
+const CHAIN_NAME: &[u8; 10] = b"mockchain\0";
+
+type NetLinkType = u16;
+
+#[derive(Debug, PartialEq)]
+enum NetlinkExpr {
+ Nested(NetLinkType, Vec<NetlinkExpr>),
+ Final(NetLinkType, Vec<u8>),
+ List(Vec<NetlinkExpr>),
+}
+
+#[derive(Debug, Error)]
+#[error("empty data")]
+struct EmptyDataError;
+
+impl NetlinkExpr {
+ fn to_raw(self) -> Vec<u8> {
+ match self {
+ NetlinkExpr::Final(ty, val) => {
+ let len = val.len() + 4;
+ let mut res = Vec::with_capacity(len);
+
+ res.extend(&(len as u16).to_le_bytes());
+ res.extend(&ty.to_le_bytes());
+ res.extend(val);
+ // alignment
+ while res.len() % 4 != 0 {
+ res.push(0);
+ }
+
+ res
+ }
+ NetlinkExpr::Nested(ty, exprs) => {
+ // some heuristic to decrease allocations (even though this is
+ // only useful for testing so performance is not an objective)
+ let mut sub = Vec::with_capacity(exprs.len() * 50);
+
+ for expr in exprs {
+ sub.append(&mut expr.to_raw());
+ }
+
+ let len = sub.len() + 4;
+ let mut res = Vec::with_capacity(len);
+
+ // set the "NESTED" flag
+ res.extend(&(len as u16).to_le_bytes());
+ res.extend(&(ty | 0x8000).to_le_bytes());
+ res.extend(sub);
+
+ res
+ }
+ NetlinkExpr::List(exprs) => {
+ // some heuristic to decrease allocations (even though this is
+ // only useful for testing so performance is not an objective)
+ let mut list = Vec::with_capacity(exprs.len() * 50);
+
+ for expr in exprs {
+ list.append(&mut expr.to_raw());
+ }
+
+ list
+ }
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+struct Nfgenmsg {
+ family: u8, /* AF_xxx */
+ version: u8, /* nfnetlink version */
+ res_id: u16, /* resource id */
+}
+
+fn get_test_rule() -> Rule {
+ let table = Rc::new(Table::new(
+ &CStr::from_bytes_with_nul(TABLE_NAME).unwrap(),
+ ProtoFamily::Inet,
+ ));
+ let chain = Rc::new(Chain::new(
+ &CStr::from_bytes_with_nul(CHAIN_NAME).unwrap(),
+ Rc::clone(&table),
+ ));
+ let rule = Rule::new(Rc::clone(&chain));
+ rule
+}
+
+fn get_test_nlmsg_from_expr(
+ rule: &mut Rule,
+ expr: &impl Expression,
+) -> (nlmsghdr, Nfgenmsg, Vec<u8>) {
+ rule.add_expr(expr);
+
+ let mut buf = vec![0u8; nft_nlmsg_maxsize() as usize];
+ unsafe {
+ rule.write(buf.as_mut_ptr() as *mut c_void, 0, MsgType::Add);
+
+ // right now the message is composed of the following parts:
+ // - nlmsghdr (contains the message size and type)
+ // - nfgenmsg (nftables header that describes the message family)
+ // - the raw expression that we want to validate
+
+ let size_of_hdr = size_of::<nlmsghdr>();
+ let size_of_nfgenmsg = size_of::<Nfgenmsg>();
+ let nlmsghdr = *(buf[0..size_of_hdr].as_ptr() as *const nlmsghdr);
+ let nfgenmsg =
+ *(buf[size_of_hdr..size_of_hdr + size_of_nfgenmsg].as_ptr() as *const Nfgenmsg);
+ let raw_expr = buf[size_of_hdr + size_of_nfgenmsg..nlmsghdr.nlmsg_len as usize]
+ .iter()
+ .map(|x| *x)
+ .collect();
+
+ // sanity checks on the global message (this should be very similar/factorisable for the
+ // most part in other tests)
+ // TODO: check the messages flags
+ assert_eq!(
+ get_subsystem_from_nlmsghdr_type(nlmsghdr.nlmsg_type),
+ NFNL_SUBSYS_NFTABLES as u8
+ );
+ assert_eq!(
+ get_operation_from_nlmsghdr_type(nlmsghdr.nlmsg_type),
+ NFT_MSG_NEWRULE as u8
+ );
+ assert_eq!(nlmsghdr.nlmsg_seq, 0);
+ assert_eq!(nlmsghdr.nlmsg_pid, 0);
+ assert_eq!(nfgenmsg.family, AF_UNIX as u8);
+ assert_eq!(nfgenmsg.version, NFNETLINK_V0 as u8);
+ assert_eq!(nfgenmsg.res_id.to_be(), 0);
+
+ (nlmsghdr, nfgenmsg, raw_expr)
+ }
+}
+
+#[test]
+fn bitwise_expr_is_valid() {
+ let netmask = Ipv4Addr::new(255, 255, 255, 0);
+ let bitwise = Bitwise::new(netmask, 0);
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &bitwise);
+ assert_eq!(nlmsghdr.nlmsg_len, 124);
+
+ 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"bitwise\0".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_BITWISE_SREG,
+ NFT_REG_1.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_BITWISE_DREG,
+ NFT_REG_1.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(NFTA_BITWISE_LEN, 4u32.to_be_bytes().to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_BITWISE_MASK,
+ vec![NetlinkExpr::Final(
+ NFTA_DATA_VALUE,
+ vec![255, 255, 255, 0]
+ )]
+ ),
+ NetlinkExpr::Nested(
+ NFTA_BITWISE_XOR,
+ vec![NetlinkExpr::Final(
+ NFTA_DATA_VALUE,
+ 0u32.to_be_bytes().to_vec()
+ )]
+ )
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[test]
+fn cmp_expr_is_valid() {
+ let cmp = Cmp::new(CmpOp::Eq, 0);
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &cmp);
+ 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"cmp\0".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(NFTA_CMP_SREG, NFT_REG_1.to_be_bytes().to_vec()),
+ NetlinkExpr::Final(NFTA_CMP_OP, NFT_CMP_EQ.to_be_bytes().to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_CMP_DATA,
+ vec![NetlinkExpr::Final(1u16, 0u32.to_be_bytes().to_vec())]
+ )
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[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 immediate_expr_is_valid() {
+ let immediate = Immediate::new(42u8, Register::Reg1);
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &immediate);
+ 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"immediate\0".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_IMMEDIATE_DREG,
+ NFT_REG_1.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Nested(
+ NFTA_IMMEDIATE_DATA,
+ vec![NetlinkExpr::Final(1u16, 42u8.to_be_bytes().to_vec())]
+ )
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[test]
+fn log_expr_is_valid() {
+ let log = Log {
+ group: Some(LogGroup(1)),
+ prefix: Some(LogPrefix::new("mockprefix").unwrap()),
+ };
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &log);
+ assert_eq!(nlmsghdr.nlmsg_len, 96);
+
+ 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"log\0".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(NFTA_LOG_PREFIX, b"mockprefix\0".to_vec()),
+ NetlinkExpr::Final(NFTA_LOG_GROUP, 1u16.to_be_bytes().to_vec())
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[test]
+fn lookup_expr_is_valid() {
+ let set_name = &CStr::from_bytes_with_nul(b"mockset\0").unwrap();
+ let mut rule = get_test_rule();
+ let table = rule.get_chain().get_table();
+ let mut set = Set::new(set_name, 0, &table, ProtoFamily::Inet);
+ let address: Ipv4Addr = [8, 8, 8, 8].into();
+ set.add(&address);
+ let lookup = Lookup::new(&set).unwrap();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &lookup);
+ assert_eq!(nlmsghdr.nlmsg_len, 104);
+
+ 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"lookup\0".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_LOOKUP_SREG,
+ NFT_REG_1.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(NFTA_LOOKUP_SET, b"mockset\0".to_vec()),
+ NetlinkExpr::Final(NFTA_LOOKUP_SET_ID, 0u32.to_be_bytes().to_vec()),
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+use rustables::expr::Masquerade;
+#[test]
+fn masquerade_expr_is_valid() {
+ let masquerade = Masquerade;
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &masquerade);
+ assert_eq!(nlmsghdr.nlmsg_len, 76);
+
+ 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"masq\0".to_vec()),
+ NetlinkExpr::Nested(NFTA_EXPR_DATA, vec![]),
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[test]
+fn meta_expr_is_valid() {
+ let meta = Meta::Protocol;
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &meta);
+ assert_eq!(nlmsghdr.nlmsg_len, 92);
+
+ 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"meta\0".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_META_KEY,
+ NFT_META_PROTOCOL.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_META_DREG,
+ NFT_REG_1.to_be_bytes().to_vec()
+ )
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[test]
+fn nat_expr_is_valid() {
+ let nat = Nat {
+ nat_type: NatType::SNat,
+ family: ProtoFamily::Ipv4,
+ ip_register: Register::Reg1,
+ port_register: None,
+ };
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &nat);
+ assert_eq!(nlmsghdr.nlmsg_len, 96);
+
+ 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"nat\0".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_NAT_TYPE,
+ NFT_NAT_SNAT.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_NAT_FAMILY,
+ // TODO find the right value to substitute here.
+ //(ProtoFamily::Ipv4 as u16).to_le_bytes().to_vec()
+ 2u32.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_NAT_REG_ADDR_MIN,
+ NFT_REG_1.to_be_bytes().to_vec()
+ )
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[test]
+fn payload_expr_is_valid() {
+ // TODO test loaded payload ?
+ let tcp_header_field = TcpHeaderField::Sport;
+ let transport_header_field = TransportHeaderField::Tcp(tcp_header_field);
+ let payload = Payload::Transport(transport_header_field);
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &payload);
+ assert_eq!(nlmsghdr.nlmsg_len, 108);
+
+ 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"payload\0".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_PAYLOAD_DREG,
+ NFT_REG_1.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_PAYLOAD_BASE,
+ NFT_PAYLOAD_TRANSPORT_HEADER.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_PAYLOAD_OFFSET,
+ tcp_header_field.offset().to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_PAYLOAD_LEN,
+ //tcp_header_field.len().to_be_bytes().to_vec()
+ 0u32.to_be_bytes().to_vec()
+ ),
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[test]
+fn reject_expr_is_valid() {
+ let code = IcmpCode::NoRoute;
+ let reject = Reject::Icmp(code);
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &reject);
+ assert_eq!(nlmsghdr.nlmsg_len, 92);
+
+ 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"reject\0".to_vec()),
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_REJECT_TYPE,
+ NFT_REJECT_ICMPX_UNREACH.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Final(
+ NFTA_REJECT_ICMP_CODE,
+ (code as u8).to_be_bytes().to_vec()
+ ),
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}
+
+#[test]
+fn verdict_expr_is_valid() {
+ let verdict = Verdict::Drop;
+ let mut rule = get_test_rule();
+ let (nlmsghdr, _nfgenmsg, raw_expr) = get_test_nlmsg_from_expr(&mut rule, &verdict);
+ assert_eq!(nlmsghdr.nlmsg_len, 104);
+
+ 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"immediate\0".to_vec()),
+ // TODO find the right arrangement for Verdict's data.
+ NetlinkExpr::Nested(
+ NFTA_EXPR_DATA,
+ vec![
+ NetlinkExpr::Final(
+ NFTA_IMMEDIATE_DREG,
+ NFT_REG_VERDICT.to_be_bytes().to_vec()
+ ),
+ NetlinkExpr::Nested(
+ NFTA_IMMEDIATE_DATA,
+ vec![NetlinkExpr::Nested(
+ NFTA_DATA_VERDICT,
+ vec![NetlinkExpr::Final(
+ NFTA_VERDICT_CODE,
+ NF_DROP.to_be_bytes().to_vec() //0u32.to_be_bytes().to_vec()
+ ),]
+ )],
+ ),
+ ]
+ )
+ ]
+ )]
+ )
+ ])
+ .to_raw()
+ );
+}