use rustables::{
expr::{ExpressionVariant, Log, RawExpression, Register, Verdict, VerdictType},
list_chains_for_table, list_rules_for_chain, list_tables, Batch, Chain, MsgType, Rule, Table,
};
const TABLE_NAME: &str = "example-table";
const CHAIN_NAME: &str = "chain-for-incoming-packets";
fn main() -> Result<(), Error> {
env_logger::init();
let get_table = || -> Result<Option<Table>, Error> {
let tables = list_tables()?;
for table in tables {
if let Some(name) = table.get_name() {
println!("Found table {}", name);
if name == TABLE_NAME {
return Ok(Some(table));
}
}
}
Ok(None)
};
let get_chain = |table: &Table| -> Result<Option<Chain>, Error> {
let chains = list_chains_for_table(table)?;
for chain in chains {
if let Some(name) = chain.get_name() {
println!("Found chain {}", name);
if name == CHAIN_NAME {
return Ok(Some(chain));
}
}
}
Ok(None)
};
let get_rule = |chain: &Chain| -> Result<Option<(u64, Rule)>, Error> {
let rules = list_rules_for_chain(&chain)?;
for mut rule in rules {
let old_handle = *rule.get_handle().expect("no handle on an existing rule!?");
println!("Found rule {}", old_handle);
if let Some(exprs) = rule.get_mut_expressions() {
let mut found = false;
for expr in exprs.iter_mut() {
if let Some(ExpressionVariant::Immediate(imm)) = expr.get_data() {
if imm.get_dreg() == Some(&Register::Verdict)
&& imm.get_data().map(|d| d.get_verdict()).flatten()
== Some(&Verdict::default().with_code(VerdictType::Accept))
{
*expr = RawExpression::from(Log::default());
found = true;
}
}
}
if found {
let rule = Rule::new(&chain)?.with_expressions(exprs.clone());
return Ok(Some((old_handle, rule)));
}
}
}
Ok(None)
};
let table = get_table()?.expect("no table?");
let chain = get_chain(&table)?.expect("no chain?");
let (old_rule_handle, new_rule) = get_rule(&chain)?.expect("no rule?");
println!("Editing rule with handle {}", old_rule_handle);
let mut batch = Batch::new();
batch.add(
&Rule::new(&chain)?.with_handle(old_rule_handle),
MsgType::Del,
);
batch.add(&new_rule, MsgType::Add);
Ok(batch.send()?)
}
#[allow(dead_code)]
#[derive(Debug)]
struct Error(String);
impl<T: std::error::Error> From<T> for Error {
fn from(error: T) -> Self {
Error(error.to_string())
}
}