use std::net::Ipv6Addr;
use std::str::FromStr;
use netlink_packet_core::{
Emitable as _, NetlinkBuffer, NetlinkMessage, Parseable, NLM_F_APPEND,
NLM_F_CREATE, NLM_F_MATCH, NLM_F_REQUEST, NLM_F_ROOT,
};
use crate::nftables::{
Bitwise, ChainAttribute, ChainMessage, ChecksumFlags, Cmp, DataAttribute,
ExpressionAttribute, Expressions, GenAttribute, GenMessage, Hook,
Immediate, InetHookNumber, ListAttribute, Lookup, Meta, MetaKey,
NfTablesMessage, Operator, Payload, Register, RuleAttribute, RuleMessage,
SetAttribute, SetElementAttribute, SetElementList, SetElementMessage,
SetFlags, SetMessage, TableAttribute, TableFlags, TableMessage, Verdict,
VerdictAttribute,
};
const NFNL_SUBSYS_NFTABLES: u8 = libc::NFNL_SUBSYS_NFTABLES as u8;
use crate::none::ControlMessage;
use crate::{NetfilterHeader, NetfilterMessage, NetfilterProtoFamily};
const IPV6_TYPE_NFT: u32 = 0x08;
fn __test(mut msg: NetlinkMessage<NetfilterMessage>, raw: Vec<u8>) {
let mut buffer = vec![0; msg.buffer_len()];
msg.finalize();
msg.emit(&mut buffer);
assert_eq!(buffer, raw, "Message wasn't correctly serialized: {msg:?}");
assert_eq!(
NetlinkMessage::parse(&NetlinkBuffer::new(&raw)).unwrap(),
msg,
);
}
#[test]
fn test_nft_list_ruleset() {
let mut msgs = Vec::with_capacity(6);
let raw_get_gen: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let get_gen = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::Unspec, 0, 0),
NfTablesMessage::GetGen(GenMessage { attributes: vec![] }),
));
msgs.push((raw_get_gen, get_gen));
let raw_get_table: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut get_table = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::Unspec, 0, 0),
NfTablesMessage::GetTable(TableMessage { attributes: vec![] }),
));
get_table.header.flags = NLM_F_ROOT | NLM_F_MATCH;
msgs.push((raw_get_table, get_table));
let raw_get_chain: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x04, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut get_chain = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::Unspec, 0, 0),
NfTablesMessage::GetChain(ChainMessage { attributes: vec![] }),
));
get_chain.header.flags = NLM_F_ROOT | NLM_F_MATCH;
msgs.push((raw_get_chain, get_chain));
let raw_get_set: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut get_set = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::Unspec, 0, 0),
NfTablesMessage::GetSet(SetMessage { attributes: vec![] }),
));
get_set.header.flags = NLM_F_ROOT | NLM_F_MATCH;
msgs.push((raw_get_set, get_set));
let raw_get_obj: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x13, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut get_obj = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::Unspec, 0, 0),
NfTablesMessage::GetObject(vec![]),
));
get_obj.header.flags = NLM_F_ROOT | NLM_F_MATCH;
msgs.push((raw_get_obj, get_obj));
let raw_get_flow_table: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x17, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut get_flow_table = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::Unspec, 0, 0),
NfTablesMessage::GetFlowTable(vec![]),
));
get_flow_table.header.flags = NLM_F_ROOT | NLM_F_MATCH;
msgs.push((raw_get_flow_table, get_flow_table));
for (raw, mut msg) in msgs {
msg.header.flags |= NLM_F_REQUEST;
__test(msg, raw);
}
let raw_new_gen: Vec<u8> = vec![
0x2c, 0x00, 0x00, 0x00, 0x0f, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xf2, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x34, 0xf2,
0x08, 0x00, 0x03, 0x00, 0x6e, 0x66, 0x74, 0x00,
];
let mut new_gen = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::Unspec, 0, 1),
NfTablesMessage::NewGen(GenMessage {
attributes: vec![
GenAttribute::Id(1),
GenAttribute::ProcPid(0x34f2),
GenAttribute::ProcName("nft".to_string()),
],
}),
));
new_gen.header.port_number = 0x34f2;
__test(new_gen, raw_new_gen);
}
#[test]
fn test_nft_load_examle_file() {
let mut msgs = Vec::with_capacity(9);
let raw_batch_begin: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
];
let batch_begin = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(
NetfilterProtoFamily::Unspec,
0,
NFNL_SUBSYS_NFTABLES as _,
),
ControlMessage::BatchBegin,
));
msgs.push((raw_batch_begin, batch_begin));
let raw_new_table: Vec<u8> = vec![
0x40, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x01, 0x00,
0x66, 0x6f, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00,
0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x06, 0x00,
0x01, 0x04, 0x01, 0x01, 0x06, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,
0x69, 0xa4, 0x96, 0x94,
];
let new_table = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::IPv6, 0, 0),
NfTablesMessage::NewTable(TableMessage {
attributes: vec![
TableAttribute::Name("foo_table".to_string()),
TableAttribute::Flags(TableFlags::default()),
TableAttribute::UserData(vec![
0x1, 0x4, 0x1, 0x1, 0x6, 0x0, 0x2, 0x8, 0x0, 0x0, 0x0, 0x0,
0x69, 0xa4, 0x96, 0x94,
]),
],
}),
));
msgs.push((raw_new_table, new_table));
let raw_hookin_chain: Vec<u8> = vec![
0x58, 0x00, 0x00, 0x00, 0x03, 0x0a, 0x01, 0x04, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x01, 0x00,
0x66, 0x6f, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00,
0x0b, 0x00, 0x03, 0x00, 0x68, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x00, 0x00,
0x08, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x07, 0x00,
0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x00, 0x00, 0x14, 0x00, 0x04, 0x80,
0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
0xff, 0xff, 0xfe, 0xd4,
];
let mut hookin_chain = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::IPv6, 0, 0),
NfTablesMessage::NewChain(ChainMessage {
attributes: vec![
ChainAttribute::Table("foo_table".to_string()),
ChainAttribute::Name("hookin".to_string()),
ChainAttribute::Policy(1), ChainAttribute::Type("filter".to_string()),
ChainAttribute::Hook(vec![
Hook::Number(InetHookNumber::PreRouting.into()),
Hook::Priority(-300 as _),
]),
],
}),
));
hookin_chain.header.flags |= NLM_F_CREATE;
msgs.push((raw_hookin_chain, hookin_chain));
let raw_forward_chain: Vec<u8> = vec![
0x30, 0x00, 0x00, 0x00, 0x03, 0x0a, 0x01, 0x04, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x01, 0x00,
0x66, 0x6f, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x03, 0x00, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x00,
];
let mut forward_chain = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::IPv6, 0, 0),
NfTablesMessage::NewChain(ChainMessage {
attributes: vec![
ChainAttribute::Table("foo_table".to_string()),
ChainAttribute::Name("forward".to_string()),
],
}),
));
forward_chain.header.flags |= NLM_F_CREATE;
msgs.push((raw_forward_chain, forward_chain));
let raw_bar_map: Vec<u8> = vec![
0x8c, 0x00, 0x00, 0x00, 0x09, 0x0a, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x01, 0x00,
0x66, 0x6f, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x02, 0x00, 0x62, 0x61, 0x72, 0x5f, 0x6d, 0x61, 0x70, 0x00,
0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10,
0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x07, 0x00,
0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x01,
0x2a, 0x00, 0x0d, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x01, 0x04,
0x02, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00,
0x01, 0x00, 0x04, 0x08, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut bar_map = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::IPv6, 0, 0),
NfTablesMessage::NewSet(SetMessage {
attributes: vec![
SetAttribute::Table("foo_table".to_string()),
SetAttribute::Name("bar_map".to_string()),
SetAttribute::Flags(SetFlags::Map),
SetAttribute::KeyType(IPV6_TYPE_NFT),
SetAttribute::KeyLen(size_of::<Ipv6Addr>() as _),
SetAttribute::DataType(IPV6_TYPE_NFT),
SetAttribute::DataLen(size_of::<Ipv6Addr>() as _),
SetAttribute::Id(1),
SetAttribute::UserData(vec![
0x0, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x4, 0x2, 0x0, 0x0, 0x0,
0x3, 0x8, 0x0, 0x4, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0x4, 0x8,
0x0, 0x4, 0x4, 0x0, 0x0, 0x0, 0x1, 0x0, 0x6, 0x4, 0x0, 0x0,
0x0, 0x0,
]),
],
}),
));
bar_map.header.flags |= NLM_F_CREATE;
msgs.push((raw_bar_map, bar_map));
let raw_hookin_rule: Vec<u8> = vec![
0xd0, 0x00, 0x00, 0x00, 0x06, 0x0a, 0x01, 0x0c, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x01, 0x00,
0x66, 0x6f, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00,
0x0b, 0x00, 0x02, 0x00, 0x68, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x00, 0x00,
0xa0, 0x00, 0x04, 0x80, 0x34, 0x00, 0x01, 0x80, 0x0c, 0x00, 0x01, 0x00,
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x00, 0x24, 0x00, 0x02, 0x80,
0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x18,
0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x2c, 0x00, 0x01, 0x80,
0x08, 0x00, 0x01, 0x00, 0x63, 0x6d, 0x70, 0x00, 0x20, 0x00, 0x02, 0x80,
0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x80, 0x08, 0x00, 0x01, 0x00,
0x20, 0x01, 0x0d, 0xb8, 0x3c, 0x00, 0x01, 0x80, 0x0e, 0x00, 0x01, 0x00,
0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00,
0x28, 0x00, 0x02, 0x80, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x02, 0x80, 0x18, 0x00, 0x02, 0x80, 0x08, 0x00, 0x01, 0x00,
0xff, 0xff, 0xff, 0xfc, 0x0c, 0x00, 0x02, 0x00, 0x66, 0x6f, 0x72, 0x77,
0x61, 0x72, 0x64, 0x00,
];
let mut hookin_rule = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::IPv6, 0, 0),
NfTablesMessage::NewRule(RuleMessage {
attributes: vec![
RuleAttribute::Table("foo_table".to_string()),
RuleAttribute::Chain("hookin".to_string()),
RuleAttribute::Expressions(vec![
Expressions::Payload(vec![
Payload::DestinationRegister(Register::Reg1),
Payload::Base(1), Payload::Offset(24), Payload::Len(4), ])
.into(),
Expressions::Cmp(vec![
Cmp::SourceRegister(Register::Reg1),
Cmp::Op(Operator::Equal),
Cmp::Data(DataAttribute::Value(vec![
0x20, 0x1, 0xd, 0xb8, ])),
])
.into(),
Expressions::Immediate(vec![
Immediate::DestinationRegister(Register::Verdict),
Immediate::Data(DataAttribute::Verdict(vec![
VerdictAttribute::Code(Verdict::Goto),
VerdictAttribute::Chain("forward".to_string()),
])),
])
.into(),
]),
],
}),
));
hookin_rule.header.flags |= NLM_F_CREATE | NLM_F_APPEND;
msgs.push((raw_hookin_rule, hookin_rule));
let raw_hookin_rule2: Vec<u8> = vec![
0x88, 0x01, 0x00, 0x00, 0x06, 0x0a, 0x01, 0x0c, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x01, 0x00,
0x66, 0x6f, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00,
0x0b, 0x00, 0x02, 0x00, 0x68, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x00, 0x00,
0x58, 0x01, 0x04, 0x80, 0x34, 0x00, 0x01, 0x80, 0x0c, 0x00, 0x01, 0x00,
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x00, 0x24, 0x00, 0x02, 0x80,
0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x18,
0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5c, 0x00, 0x01, 0x80,
0x0c, 0x00, 0x01, 0x00, 0x62, 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, 0x00,
0x4c, 0x00, 0x02, 0x80, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x03, 0x00,
0x00, 0x00, 0x00, 0x10, 0x18, 0x00, 0x04, 0x80, 0x14, 0x00, 0x01, 0x00,
0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x05, 0x80, 0x14, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x80, 0x08, 0x00, 0x01, 0x00,
0x63, 0x6d, 0x70, 0x00, 0x2c, 0x00, 0x02, 0x80, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x03, 0x80, 0x14, 0x00, 0x01, 0x00, 0x3f, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x00, 0x01, 0x80, 0x09, 0x00, 0x01, 0x00, 0x6d, 0x65, 0x74, 0x61,
0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x80, 0x08, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
0x2c, 0x00, 0x01, 0x80, 0x08, 0x00, 0x01, 0x00, 0x63, 0x6d, 0x70, 0x00,
0x20, 0x00, 0x02, 0x80, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x03, 0x80,
0x05, 0x00, 0x01, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x01, 0x80,
0x0e, 0x00, 0x01, 0x00, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74,
0x65, 0x00, 0x00, 0x00, 0x28, 0x00, 0x02, 0x80, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x80, 0x18, 0x00, 0x02, 0x80,
0x08, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x0c, 0x00, 0x02, 0x00,
0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x00,
];
let mut hookin_rule2 = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::IPv6, 0, 0),
NfTablesMessage::NewRule(RuleMessage {
attributes: vec![
RuleAttribute::Table("foo_table".to_string()),
RuleAttribute::Chain("hookin".to_string()),
RuleAttribute::Expressions(vec![
Expressions::Payload(vec![
Payload::DestinationRegister(Register::Reg1),
Payload::Base(1), Payload::Offset(24), Payload::Len(size_of::<Ipv6Addr>() as _),
])
.into(),
Expressions::Bitwise(vec![
Bitwise::SourceRegister(Register::Reg1),
Bitwise::DestinationRegister(Register::Reg1),
Bitwise::Length(16),
Bitwise::Mask(DataAttribute::Value(vec![
0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ])),
Bitwise::Xor(DataAttribute::Value(vec![0; 16])),
])
.into(),
Expressions::Cmp(vec![
Cmp::SourceRegister(Register::Reg1),
Cmp::Op(Operator::Equal),
Cmp::Data(DataAttribute::Value(
Ipv6Addr::from_str("3fff::")
.unwrap()
.octets()
.to_vec(),
)),
])
.into(),
Expressions::Meta(vec![
Meta::Key(MetaKey::L4Proto),
Meta::DestinationRegister(Register::Reg1),
])
.into(),
Expressions::Cmp(vec![
Cmp::SourceRegister(Register::Reg1),
Cmp::Op(Operator::NotEqual),
Cmp::Data(DataAttribute::Value(vec![0x3a])),
])
.into(),
Expressions::Immediate(vec![
Immediate::DestinationRegister(Register::Verdict),
Immediate::Data(DataAttribute::Verdict(vec![
VerdictAttribute::Code(Verdict::Goto),
VerdictAttribute::Chain("forward".to_string()),
])),
])
.into(),
]),
],
}),
));
hookin_rule2.header.flags |= NLM_F_CREATE | NLM_F_APPEND;
msgs.push((raw_hookin_rule2, hookin_rule2));
let raw_forward_rule: Vec<u8> = vec![
0xec, 0x00, 0x00, 0x00, 0x06, 0x0a, 0x01, 0x0c, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x01, 0x00,
0x66, 0x6f, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x02, 0x00, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x00,
0xbc, 0x00, 0x04, 0x80, 0x34, 0x00, 0x01, 0x80, 0x0c, 0x00, 0x01, 0x00,
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x00, 0x24, 0x00, 0x02, 0x80,
0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x18,
0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x01, 0x80,
0x0b, 0x00, 0x01, 0x00, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x00, 0x00,
0x28, 0x00, 0x02, 0x80, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01,
0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x01, 0x00,
0x62, 0x61, 0x72, 0x5f, 0x6d, 0x61, 0x70, 0x00, 0x08, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x01, 0x80, 0x0c, 0x00, 0x01, 0x00,
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x00, 0x2c, 0x00, 0x02, 0x80,
0x08, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x18,
0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x01, 0x80, 0x0c, 0x00, 0x01, 0x00,
0x6e, 0x6f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x00,
];
let mut forward_rule = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::IPv6, 0, 0),
NfTablesMessage::NewRule(RuleMessage {
attributes: vec![
RuleAttribute::Table("foo_table".to_string()),
RuleAttribute::Chain("forward".to_string()),
RuleAttribute::Expressions(vec![
Expressions::Payload(vec![
Payload::DestinationRegister(Register::Reg1),
Payload::Base(1), Payload::Offset(24), Payload::Len(size_of::<Ipv6Addr>() as _),
])
.into(),
Expressions::Lookup(vec![
Lookup::SourceRegister(Register::Reg1),
Lookup::DestinationRegister(Register::Reg1),
Lookup::Set("bar_map".to_string()),
Lookup::SetId(1),
])
.into(),
Expressions::Payload(vec![
Payload::SourceRegister(Register::Reg1),
Payload::Base(1), Payload::Offset(24), Payload::Len(size_of::<Ipv6Addr>() as _),
Payload::CsumFlags(
ChecksumFlags::L4PseudoHeader,
),
])
.into(),
ListAttribute::Element(vec![
ExpressionAttribute::Name(
"notrack".to_string(),
),
]),
]),
],
}),
));
forward_rule.header.flags |= NLM_F_CREATE | NLM_F_APPEND;
msgs.push((raw_forward_rule, forward_rule));
let raw_batch_end: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
];
let batch_end = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(
NetfilterProtoFamily::Unspec,
0,
NFNL_SUBSYS_NFTABLES as _,
),
ControlMessage::BatchEnd,
));
msgs.push((raw_batch_end, batch_end));
for (seq_nr, (raw, mut msg)) in msgs.into_iter().enumerate() {
msg.header.flags |= NLM_F_REQUEST; msg.header.sequence_number = seq_nr as _;
__test(msg, raw);
}
}
#[test]
fn test_nft_add_map_element() {
let mut msgs = Vec::with_capacity(3);
let raw_batch_begin: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
];
let batch_begin = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(
NetfilterProtoFamily::Unspec,
0,
NFNL_SUBSYS_NFTABLES as _,
),
ControlMessage::BatchBegin,
));
msgs.push((raw_batch_begin, batch_begin));
let raw_set_elem: Vec<u8> = vec![
0x70, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x01, 0x04, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x01, 0x00,
0x66, 0x6f, 0x6f, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x02, 0x00, 0x62, 0x61, 0x72, 0x5f, 0x6d, 0x61, 0x70, 0x00,
0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x00, 0x03, 0x80,
0x34, 0x00, 0x01, 0x80, 0x18, 0x00, 0x01, 0x80, 0x14, 0x00, 0x01, 0x00,
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x02, 0x80, 0x14, 0x00, 0x01, 0x00,
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02,
];
let mut set_elem = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(NetfilterProtoFamily::IPv6, 0, 0),
NfTablesMessage::NewSetElement(SetElementMessage {
attributes: vec![
SetElementList::Table("foo_table".to_string()),
SetElementList::Set("bar_map".to_string()),
SetElementList::SetId(1),
SetElementList::Elements(vec![ListAttribute::Element(vec![
SetElementAttribute::Key(DataAttribute::Value(
Ipv6Addr::from_str("2001:db8::1")
.unwrap()
.octets()
.to_vec(),
)),
SetElementAttribute::Data(DataAttribute::Value(
Ipv6Addr::from_str("2001:db8::2")
.unwrap()
.octets()
.to_vec(),
)),
])]),
],
}),
));
set_elem.header.flags |= NLM_F_CREATE;
msgs.push((raw_set_elem, set_elem));
let raw_batch_end: Vec<u8> = vec![
0x14, 0x00, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
];
let batch_end = NetlinkMessage::from(NetfilterMessage::new(
NetfilterHeader::new(
NetfilterProtoFamily::Unspec,
0,
NFNL_SUBSYS_NFTABLES as _,
),
ControlMessage::BatchEnd,
));
msgs.push((raw_batch_end, batch_end));
for (seq_nr, (raw, mut msg)) in msgs.into_iter().enumerate() {
msg.header.flags |= NLM_F_REQUEST; msg.header.sequence_number = seq_nr as _;
__test(msg, raw);
}
}