diff options
-rw-r--r-- | rustables/examples/add-rules.rs | 67 | ||||
-rw-r--r-- | rustables/examples/filter-ethernet.rs | 41 |
2 files changed, 60 insertions, 48 deletions
diff --git a/rustables/examples/add-rules.rs b/rustables/examples/add-rules.rs index d114ef1..4fea491 100644 --- a/rustables/examples/add-rules.rs +++ b/rustables/examples/add-rules.rs @@ -37,11 +37,12 @@ //! ``` use ipnetwork::{IpNetwork, Ipv4Network}; -use nftnl::{nft_expr, nftnl_sys::libc, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table}; +use rustables::{nft_expr, rustables_sys::libc, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table}; use std::{ ffi::{self, CString}, io, net::Ipv4Addr, + rc::Rc }; const TABLE_NAME: &str = "example-table"; @@ -55,34 +56,37 @@ fn main() -> Result<(), Error> { let mut batch = Batch::new(); // Create a netfilter table operating on both IPv4 and IPv6 (ProtoFamily::Inet) - let table = Table::new(&CString::new(TABLE_NAME).unwrap(), ProtoFamily::Inet); + let table = Rc::new(Table::new(&CString::new(TABLE_NAME).unwrap(), ProtoFamily::Inet)); // Add the table to the batch with the `MsgType::Add` type, thus instructing netfilter to add // this table under its `ProtoFamily::Inet` ruleset. - batch.add(&table, nftnl::MsgType::Add); + batch.add(&Rc::clone(&table), rustables::MsgType::Add); // Create input and output chains under the table we created above. - let mut out_chain = Chain::new(&CString::new(OUT_CHAIN_NAME).unwrap(), &table); - let mut in_chain = Chain::new(&CString::new(IN_CHAIN_NAME).unwrap(), &table); - // Hook the chains to the input and output event hooks, with highest priority (priority zero). // See the `Chain::set_hook` documentation for details. - out_chain.set_hook(nftnl::Hook::Out, 0); - in_chain.set_hook(nftnl::Hook::In, 0); + let mut out_chain = Chain::new(&CString::new(OUT_CHAIN_NAME).unwrap(), Rc::clone(&table)); + let mut in_chain = Chain::new(&CString::new(IN_CHAIN_NAME).unwrap(), Rc::clone(&table)); + + out_chain.set_hook(rustables::Hook::Out, 0); + in_chain.set_hook(rustables::Hook::In, 0); // Set the default policies on the chains. If no rule matches a packet processed by the // `out_chain` or the `in_chain` it will accept the packet. - out_chain.set_policy(nftnl::Policy::Accept); - in_chain.set_policy(nftnl::Policy::Accept); + out_chain.set_policy(rustables::Policy::Accept); + in_chain.set_policy(rustables::Policy::Accept); + + let out_chain = Rc::new(out_chain); + let in_chain = Rc::new(in_chain); // Add the two chains to the batch with the `MsgType` to tell netfilter to create the chains // under the table. - batch.add(&out_chain, nftnl::MsgType::Add); - batch.add(&in_chain, nftnl::MsgType::Add); + batch.add(&Rc::clone(&out_chain), rustables::MsgType::Add); + batch.add(&Rc::clone(&in_chain), rustables::MsgType::Add); // === ADD RULE ALLOWING ALL TRAFFIC TO THE LOOPBACK DEVICE === // Create a new rule object under the input chain. - let mut allow_loopback_in_rule = Rule::new(&in_chain); + let mut allow_loopback_in_rule = Rule::new(Rc::clone(&in_chain)); // Lookup the interface index of the loopback interface. let lo_iface_index = iface_index("lo")?; @@ -103,11 +107,11 @@ fn main() -> Result<(), Error> { allow_loopback_in_rule.add_expr(&nft_expr!(verdict accept)); // Add the rule to the batch. - batch.add(&allow_loopback_in_rule, nftnl::MsgType::Add); + batch.add(&allow_loopback_in_rule, rustables::MsgType::Add); // === ADD A RULE ALLOWING (AND COUNTING) ALL PACKETS TO THE 10.1.0.0/24 NETWORK === - let mut block_out_to_private_net_rule = Rule::new(&out_chain); + let mut block_out_to_private_net_rule = Rule::new(Rc::clone(&out_chain)); let private_net_ip = Ipv4Addr::new(10, 1, 0, 0); let private_net_prefix = 24; let private_net = IpNetwork::V4(Ipv4Network::new(private_net_ip, private_net_prefix)?); @@ -140,11 +144,11 @@ fn main() -> Result<(), Error> { // Add the rule to the batch. Without this nothing would be sent over netlink and netfilter, // and all the work on `block_out_to_private_net_rule` so far would go to waste. - batch.add(&block_out_to_private_net_rule, nftnl::MsgType::Add); + batch.add(&block_out_to_private_net_rule, rustables::MsgType::Add); // === ADD A RULE ALLOWING ALL OUTGOING ICMPv6 PACKETS WITH TYPE 133 AND CODE 0 === - let mut allow_router_solicitation = Rule::new(&out_chain); + let mut allow_router_solicitation = Rule::new(Rc::clone(&out_chain)); // Check that the packet is IPv6 and ICMPv6 allow_router_solicitation.add_expr(&nft_expr!(meta nfproto)); @@ -152,18 +156,18 @@ fn main() -> Result<(), Error> { allow_router_solicitation.add_expr(&nft_expr!(meta l4proto)); allow_router_solicitation.add_expr(&nft_expr!(cmp == libc::IPPROTO_ICMPV6 as u8)); - allow_router_solicitation.add_expr(&nftnl::expr::Payload::Transport( - nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Type), + allow_router_solicitation.add_expr(&rustables::expr::Payload::Transport( + rustables::expr::TransportHeaderField::Icmpv6(rustables::expr::Icmpv6HeaderField::Type), )); allow_router_solicitation.add_expr(&nft_expr!(cmp == 133u8)); - allow_router_solicitation.add_expr(&nftnl::expr::Payload::Transport( - nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Code), + allow_router_solicitation.add_expr(&rustables::expr::Payload::Transport( + rustables::expr::TransportHeaderField::Icmpv6(rustables::expr::Icmpv6HeaderField::Code), )); allow_router_solicitation.add_expr(&nft_expr!(cmp == 0u8)); allow_router_solicitation.add_expr(&nft_expr!(verdict accept)); - batch.add(&allow_router_solicitation, nftnl::MsgType::Add); + batch.add(&allow_router_solicitation, rustables::MsgType::Add); // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER === @@ -171,11 +175,14 @@ fn main() -> Result<(), Error> { // netfilter the we reached the end of the transaction message. It's also converted to a type // that implements `IntoIterator<Item = &'a [u8]>`, thus allowing us to get the raw netlink data // out so it can be sent over a netlink socket to netfilter. - let finalized_batch = batch.finalize(); - - // Send the entire batch and process any returned messages. - send_and_process(&finalized_batch)?; - Ok(()) + match batch.finalize() { + Some(mut finalized_batch) => { + // Send the entire batch and process any returned messages. + send_and_process(&mut finalized_batch)?; + Ok(()) + }, + None => todo!() + } } // Look up the interface index for a given interface name. @@ -189,15 +196,15 @@ fn iface_index(name: &str) -> Result<libc::c_uint, Error> { } } -fn send_and_process(batch: &FinalizedBatch) -> Result<(), Error> { +fn send_and_process(batch: &mut FinalizedBatch) -> Result<(), Error> { // Create a netlink socket to netfilter. let socket = mnl::Socket::new(mnl::Bus::Netfilter)?; // Send all the bytes in the batch. - socket.send_all(batch)?; + socket.send_all(&mut *batch)?; // Try to parse the messages coming back from netfilter. This part is still very unclear. let portid = socket.portid(); - let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize]; + let mut buffer = vec![0; rustables::nft_nlmsg_maxsize() as usize]; let very_unclear_what_this_is_for = 2; while let Some(message) = socket_recv(&socket, &mut buffer[..])? { match mnl::cb_run(message, very_unclear_what_this_is_for, portid)? { diff --git a/rustables/examples/filter-ethernet.rs b/rustables/examples/filter-ethernet.rs index 6cebfc4..23be8a1 100644 --- a/rustables/examples/filter-ethernet.rs +++ b/rustables/examples/filter-ethernet.rs @@ -22,8 +22,8 @@ //! # nft delete table inet example-filter-ethernet //! ``` -use nftnl::{nft_expr, nftnl_sys::libc, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table}; -use std::{ffi::CString, io}; +use rustables::{nft_expr, rustables_sys::libc, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table}; +use std::{ffi::CString, io, rc::Rc}; const TABLE_NAME: &str = "example-filter-ethernet"; const OUT_CHAIN_NAME: &str = "chain-for-outgoing-packets"; @@ -34,17 +34,18 @@ fn main() -> Result<(), Error> { // 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(&CString::new(TABLE_NAME).unwrap(), ProtoFamily::Inet); - batch.add(&table, nftnl::MsgType::Add); + 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(), &table); - out_chain.set_hook(nftnl::Hook::Out, 3); - out_chain.set_policy(nftnl::Policy::Accept); - batch.add(&out_chain, nftnl::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(&out_chain); + 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. @@ -58,7 +59,7 @@ fn main() -> Result<(), Error> { // Drop the matching packets. block_ethernet_rule.add_expr(&nft_expr!(verdict drop)); - batch.add(&block_ethernet_rule, nftnl::MsgType::Add); + batch.add(&block_ethernet_rule, rustables::MsgType::Add); // === FOR FUN, ADD A PACKET THAT MATCHES 50% OF ALL PACKETS === @@ -66,7 +67,7 @@ fn main() -> Result<(), Error> { // 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); + 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)); @@ -79,24 +80,28 @@ fn main() -> Result<(), Error> { // 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, nftnl::MsgType::Add); + batch.add(&random_rule, rustables::MsgType::Add); // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER === - let finalized_batch = batch.finalize(); - send_and_process(&finalized_batch)?; - Ok(()) + match batch.finalize() { + Some(mut finalized_batch) => { + send_and_process(&mut finalized_batch)?; + Ok(()) + }, + None => todo!() + } } -fn send_and_process(batch: &FinalizedBatch) -> Result<(), Error> { +fn send_and_process(batch: &mut FinalizedBatch) -> Result<(), Error> { // Create a netlink socket to netfilter. let socket = mnl::Socket::new(mnl::Bus::Netfilter)?; // Send all the bytes in the batch. - socket.send_all(batch)?; + socket.send_all(&mut *batch)?; // Try to parse the messages coming back from netfilter. This part is still very unclear. let portid = socket.portid(); - let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize]; + let mut buffer = vec![0; rustables::nft_nlmsg_maxsize() as usize]; let very_unclear_what_this_is_for = 2; while let Some(message) = socket_recv(&socket, &mut buffer[..])? { match mnl::cb_run(message, very_unclear_what_this_is_for, portid)? { |