use crate::error::{NetavarkError, NetavarkResult};
use iptables::IPTables;
use log::debug;
pub fn append_unique(
driver: &IPTables,
table: &str,
chain: &str,
rule: &str,
) -> NetavarkResult<()> {
let exists = match driver.exists(table, chain, rule) {
Ok(b) => b,
Err(e) => return Err(NetavarkError::Message(e.to_string())),
};
if exists {
debug_rule_exists(table, chain, rule.to_string());
return Ok(());
}
if let Err(e) = driver
.append(table, chain, rule)
.map(|_| debug_rule_create(table, chain, rule.to_string()))
{
return Err(NetavarkError::Message(format!(
"unable to append rule '{rule}' to table '{table}': {e}",
)));
}
Result::Ok(())
}
pub fn add_chain_unique(driver: &IPTables, table: &str, new_chain: &str) -> NetavarkResult<()> {
let exists = chain_exists(driver, table, new_chain)?;
if exists {
debug_chain_exists(table, new_chain);
return Ok(());
}
match driver
.new_chain(table, new_chain)
.map(|_| debug_chain_create(table, new_chain))
{
Ok(_) => Ok(()),
Err(e) => Err(NetavarkError::Message(e.to_string())),
}
}
fn chain_exists(driver: &IPTables, table: &str, chain: &str) -> NetavarkResult<bool> {
let c = match driver.list_chains(table) {
Ok(b) => b,
Err(e) => return Err(NetavarkError::Message(e.to_string())),
};
if c.iter().any(|i| i == chain) {
debug_chain_exists(table, chain);
return serde::__private::Result::Ok(true);
}
serde::__private::Result::Ok(false)
}
pub fn remove_if_rule_exists(
driver: &IPTables,
table: &str,
chain: &str,
rule: &str,
) -> NetavarkResult<()> {
let exists = match driver.exists(table, chain, rule) {
Ok(b) => b,
Err(e) => return Err(NetavarkError::Message(e.to_string())),
};
if !exists {
debug_rule_no_exists(table, chain, rule.to_string());
return Ok(());
}
if let Err(e) = driver.delete(table, chain, rule) {
return Err(NetavarkError::Message(format!(
"failed to remove rule '{rule}' from table '{chain}': {e}"
)));
}
Result::Ok(())
}
fn debug_chain_create(table: &str, chain: &str) {
debug!("chain {} created on table {}", chain, table);
}
fn debug_chain_exists(table: &str, chain: &str) {
debug!("chain {} exists on table {}", chain, table);
}
pub fn debug_rule_create(table: &str, chain: &str, rule: String) {
debug!(
"rule {} created on table {} and chain {}",
rule, table, chain
);
}
fn debug_rule_exists(table: &str, chain: &str, rule: String) {
debug!(
"rule {} exists on table {} and chain {}",
rule, table, chain
);
}
fn debug_rule_no_exists(table: &str, chain: &str, rule: String) {
debug!(
"no rule {} exists on table {} and chain {}",
rule, table, chain
);
}