66 lines
1.9 KiB
Rust
66 lines
1.9 KiB
Rust
use nftnl::{nft_expr, set::Set, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table};
|
|
use std::{ffi::CString, io::*, net::Ipv4Addr};
|
|
|
|
fn main() -> std::result::Result<(), Error> {
|
|
let table_name = format!("ipblc4");
|
|
let table = Table::new(
|
|
&CString::new(format!("{table_name}")).unwrap(),
|
|
ProtoFamily::Ipv4,
|
|
);
|
|
|
|
let mut batch = Batch::new();
|
|
|
|
batch.add(&table, nftnl::MsgType::Add);
|
|
batch.add(&table, nftnl::MsgType::Del);
|
|
|
|
batch.add(&table, nftnl::MsgType::Add);
|
|
|
|
let mut chain = Chain::new(&CString::new("test").unwrap(), &table);
|
|
chain.set_hook(nftnl::Hook::In, 1);
|
|
chain.set_policy(nftnl::Policy::Accept);
|
|
|
|
batch.add(&chain, nftnl::MsgType::Add);
|
|
batch.add(&Rule::new(&chain), nftnl::MsgType::Del);
|
|
|
|
let mut rule = Rule::new(&chain);
|
|
|
|
rule.add_expr(&nft_expr!(ct state));
|
|
rule.add_expr(&nft_expr!(bitwise mask 4u32, xor 0u32));
|
|
rule.add_expr(&nft_expr!(cmp != 0u32));
|
|
rule.add_expr(&nft_expr!(counter));
|
|
rule.add_expr(&nft_expr!(verdict accept));
|
|
|
|
batch.add(&rule, nftnl::MsgType::Add);
|
|
let finalized_batch = batch.finalize();
|
|
send_and_process(&finalized_batch)?;
|
|
Ok(())
|
|
}
|
|
|
|
fn send_and_process(batch: &FinalizedBatch) -> std::result::Result<(), Error> {
|
|
let seq: u32 = 2;
|
|
let socket = mnl::Socket::new(mnl::Bus::Netfilter)?;
|
|
socket.send_all(batch)?;
|
|
let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize];
|
|
while let Some(message) = socket_recv(&socket, &mut buffer[..])? {
|
|
match mnl::cb_run(message, seq, socket.portid())? {
|
|
mnl::CbResult::Stop => {
|
|
break;
|
|
}
|
|
mnl::CbResult::Ok => (),
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn socket_recv<'a>(
|
|
socket: &mnl::Socket,
|
|
buf: &'a mut [u8],
|
|
) -> std::result::Result<Option<&'a [u8]>, Error> {
|
|
let ret = socket.recv(buf)?;
|
|
if ret > 0 {
|
|
Ok(Some(&buf[..ret]))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|