aboutsummaryrefslogtreecommitdiff
path: root/examples/filter-ethernet.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/filter-ethernet.rs')
-rw-r--r--examples/filter-ethernet.rs145
1 files changed, 74 insertions, 71 deletions
diff --git a/examples/filter-ethernet.rs b/examples/filter-ethernet.rs
index 732c8cb..a136731 100644
--- a/examples/filter-ethernet.rs
+++ b/examples/filter-ethernet.rs
@@ -10,7 +10,7 @@
///! table inet example-filter-ethernet {
///! chain chain-for-outgoing-packets {
///! type filter hook output priority 3; policy accept;
-///! ether daddr 00:00:00:00:00:00 drop
+///! ether daddr 01:02:03:04:05:06 drop
///! counter packets 0 bytes 0 meta random > 2147483647 counter packets 0 bytes 0
///! }
///! }
@@ -21,75 +21,78 @@
///! ```bash
///! # nft delete table inet example-filter-ethernet
///! ```
-//use rustables::{nft_expr, query::send_batch, sys::libc, Batch, Chain, ProtoFamily, Rule, Table};
-use std::{ffi::CString, rc::Rc};
-//
-//const TABLE_NAME: &str = "example-filter-ethernet";
-//const OUT_CHAIN_NAME: &str = "chain-for-outgoing-packets";
-//
-//const BLOCK_THIS_MAC: &[u8] = &[0, 0, 0, 0, 0, 0];
-//
+use rustables::{
+ expr::{
+ Cmp, CmpOp, Counter, ExpressionList, HighLevelPayload, Immediate, LLHeaderField, Meta,
+ MetaType, VerdictKind,
+ },
+ Batch, Chain, ChainPolicy, Hook, HookClass, ProtocolFamily, Rule, Table,
+};
+
+const TABLE_NAME: &str = "example-filter-ethernet";
+const OUT_CHAIN_NAME: &str = "chain-for-outgoing-packets";
+
+const BLOCK_THIS_MAC: &[u8] = &[1, 2, 3, 4, 5, 6];
+
fn main() {
- // // For verbose explanations of what all these lines up until the rule creation does, see the
- // // `add-rules` example.
- // let mut batch = Batch::new();
- // let table = Rc::new(Table::new(
- // &CString::new(TABLE_NAME).unwrap(),
- // ProtoFamily::Inet,
- // ));
- // batch.add(&Rc::clone(&table), rustables::MsgType::Add);
- //
- // let mut out_chain = Chain::new(&CString::new(OUT_CHAIN_NAME).unwrap(), Rc::clone(&table));
- // out_chain.set_hook(rustables::Hook::Out, 3);
- // out_chain.set_policy(rustables::Policy::Accept);
- // let out_chain = Rc::new(out_chain);
- // batch.add(&Rc::clone(&out_chain), rustables::MsgType::Add);
- //
- // // === ADD RULE DROPPING ALL TRAFFIC TO THE MAC ADDRESS IN `BLOCK_THIS_MAC` ===
- //
- // let mut block_ethernet_rule = Rule::new(Rc::clone(&out_chain));
- //
- // // Check that the interface type is an ethernet interface. Must be done before we can check
- // // payload values in the ethernet header.
- // block_ethernet_rule.add_expr(&nft_expr!(meta iiftype));
- // block_ethernet_rule.add_expr(&nft_expr!(cmp == libc::ARPHRD_ETHER));
- //
- // // Compare the ethernet destination address against the MAC address we want to drop
- // block_ethernet_rule.add_expr(&nft_expr!(payload ethernet daddr));
- // block_ethernet_rule.add_expr(&nft_expr!(cmp == BLOCK_THIS_MAC));
- //
- // // Drop the matching packets.
- // block_ethernet_rule.add_expr(&nft_expr!(verdict drop));
- //
- // batch.add(&block_ethernet_rule, rustables::MsgType::Add);
- //
- // // === FOR FUN, ADD A PACKET THAT MATCHES 50% OF ALL PACKETS ===
- //
- // // This packet has a counter before and after the check that has 50% chance of matching.
- // // So after a number of packets has passed through this rule, the first counter should have a
- // // value approximately double that of the second counter. This rule has no verdict, so it never
- // // does anything with the matching packets.
- // let mut random_rule = Rule::new(Rc::clone(&out_chain));
- // // This counter expression will be evaluated (and increment the counter) for all packets coming
- // // through.
- // random_rule.add_expr(&nft_expr!(counter));
- //
- // // Load a pseudo-random 32 bit unsigned integer into the netfilter register.
- // random_rule.add_expr(&nft_expr!(meta random));
- // // Check if the random integer is larger than `u32::MAX/2`, thus having 50% chance of success.
- // random_rule.add_expr(&nft_expr!(cmp > (::std::u32::MAX / 2).to_be()));
- //
- // // Add a second counter. This will only be incremented for the packets passing the random check.
- // random_rule.add_expr(&nft_expr!(counter));
- //
- // batch.add(&random_rule, rustables::MsgType::Add);
- //
- // // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER ===
- //
- // match batch.finalize() {
- // Some(mut finalized_batch) => {
- // send_batch(&mut finalized_batch).expect("Couldn't process the batch");
- // }
- // None => todo!(),
- // }
+ // For verbose explanations of what all these lines up until the rule creation does, see the
+ // `add-rules` example.
+ let mut batch = Batch::new();
+ let table = Table::new(ProtocolFamily::Inet).with_name(TABLE_NAME);
+ batch.add(&table, rustables::MsgType::Add);
+
+ let mut out_chain = Chain::new(&table).with_name(OUT_CHAIN_NAME);
+ out_chain.set_hook(Hook::new(HookClass::Out, 3));
+ out_chain.set_policy(ChainPolicy::Accept);
+ batch.add(&out_chain, rustables::MsgType::Add);
+
+ // === ADD RULE DROPPING ALL TRAFFIC TO THE MAC ADDRESS IN `BLOCK_THIS_MAC` ===
+
+ let mut block_ethernet_rule = Rule::new(&out_chain).unwrap();
+
+ block_ethernet_rule.set_expressions(
+ ExpressionList::default()
+ // Check that the interface type is an ethernet interface. Must be done before we can check
+ // payload values in the ethernet header.
+ .with_value(Meta::new(MetaType::IifType))
+ .with_value(Cmp::new(CmpOp::Eq, (libc::ARPHRD_ETHER as u16).to_le_bytes()))
+
+ // Compare the ethernet destination address against the MAC address we want to drop
+ .with_value(HighLevelPayload::LinkLayer(LLHeaderField::Daddr).build())
+ .with_value(Cmp::new(CmpOp::Eq, BLOCK_THIS_MAC))
+
+ // Drop the matching packets.
+ .with_value(Immediate::new_verdict(VerdictKind::Drop)),
+ );
+
+ batch.add(&block_ethernet_rule, rustables::MsgType::Add);
+
+ // === FOR FUN, ADD A PACKET THAT MATCHES 50% OF ALL PACKETS ===
+
+ // This packet has a counter before and after the check that has 50% chance of matching.
+ // So after a number of packets has passed through this rule, the first counter should have a
+ // value approximately double that of the second counter. This rule has no verdict, so it never
+ // does anything with the matching packets.
+ let mut random_rule = Rule::new(&out_chain).unwrap();
+
+ random_rule.set_expressions(
+ ExpressionList::default()
+ // This counter expression will be evaluated (and increment the counter) for all packets coming
+ // through.
+ .with_value(Counter::default())
+
+ // Load a pseudo-random 32 bit unsigned integer into the netfilter register.
+ .with_value(Meta::new(MetaType::PRandom))
+ // Check if the random integer is larger than `u32::MAX/2`, thus having 50% chance of success.
+ .with_value(Cmp::new(CmpOp::Gt, (::std::u32::MAX / 2).to_be_bytes()))
+
+ // Add a second counter. This will only be incremented for the packets passing the random check.
+ .with_value(Counter::default()),
+ );
+
+ batch.add(&random_rule, rustables::MsgType::Add);
+
+ // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER ===
+
+ batch.send().unwrap();
}