use nlink::netlink::nftables::config::NftablesConfig;
use nlink::netlink::nftables::types::{Family, Hook, Policy, Priority};
use nlink::netlink::{Connection, Nftables};
#[tokio::main]
async fn main() -> nlink::Result<()> {
let conn = Connection::<Nftables>::new()?;
let cfg = NftablesConfig::new().table("filter_demo", Family::Inet, |t| {
t.chain("input", |c| {
c.hook(Hook::Input)
.priority(Priority::Filter)
.policy(Policy::Drop)
})
.rule_keyed("input", "ssh-allow", |r| r.match_tcp_dport(22).accept())
.rule_keyed("input", "icmp-allow", |r| {
r.match_l4proto(1 ).accept()
})
});
let diff = match cfg.diff(&conn).await {
Ok(d) => d,
Err(e) if e.is_permission_denied() => {
eprintln!(
"EPERM: nftables config diff requires CAP_NET_ADMIN; \
re-run with sudo (rule integrity end-to-end demo)",
);
return Ok(());
}
Err(e) => return Err(e),
};
println!("initial diff:\n{}", diff.summary());
let applied = diff.apply(&conn).await?;
println!("\napplied {applied} ops\n");
let reapply_diff = cfg.diff(&conn).await?;
assert!(
reapply_diff.is_empty(),
"idempotent re-apply should produce empty diff; got: {}",
reapply_diff.summary(),
);
println!("reapply diff: {} (empty — idempotent ✓)\n", reapply_diff.summary());
let updated = NftablesConfig::new().table("filter_demo", Family::Inet, |t| {
t.chain("input", |c| {
c.hook(Hook::Input)
.priority(Priority::Filter)
.policy(Policy::Drop)
})
.rule_keyed("input", "ssh-allow", |r| r.match_tcp_dport(2222).accept()) .rule_keyed("input", "icmp-allow", |r| r.match_l4proto(1).accept())
});
let mut_diff = updated.diff(&conn).await?;
println!("after port change:\n{}", mut_diff.summary());
assert_eq!(
mut_diff.rules_to_replace.len(),
1,
"expected exactly one in-place replace for the changed rule",
);
let applied = mut_diff.apply(&conn).await?;
println!("\napplied {applied} op (1 = single replace_rule via NLM_F_REPLACE)\n");
let teardown = NftablesConfig::new(); let drop_diff = teardown.diff(&conn).await?;
println!("teardown diff:\n{}", drop_diff.summary());
let applied = drop_diff.apply(&conn).await?;
println!("\nteardown applied {applied} ops — demo complete");
Ok(())
}