use std::io;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::process::{Command, Stdio};
use crate::builders::ipv4_builder::Ipv4Builder;
use crate::builders::ipv6_builder::Ipv6Builder;
use crate::builders::port_builder::PortBuilder;
use crate::command::CommandRunner;
use crate::error::UfwError;
use crate::models::{IpRule, PortRule};
use crate::parser::{parse_ip_rules, parse_is_enabled, parse_port_rules};
pub struct Firewall;
impl Default for Firewall {
fn default() -> Self {
Firewall
}
}
impl Firewall {
pub fn new() -> Self {
Firewall
}
pub fn is_installed(&self) -> Result<bool, UfwError> {
match Command::new("ufw")
.arg("--help")
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
{
Ok(status) => Ok(status.success()),
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(false),
Err(e) => Err(UfwError::Io(e)),
}
}
pub fn is_enabled(&self) -> Result<bool, UfwError> {
let raw = CommandRunner::output("sudo", &["ufw", "status"])?;
parse_is_enabled(&raw)
}
pub fn enable(&self) -> Result<(), UfwError> {
CommandRunner::run("sudo", &["ufw", "--force", "enable"])
}
pub fn disable(&self) -> Result<(), UfwError> {
CommandRunner::run("sudo", &["ufw", "disable"])
}
pub fn reload(&self) -> Result<(), UfwError> {
CommandRunner::run("sudo", &["ufw", "reload"])
}
pub fn reset(&self) -> Result<(), UfwError> {
CommandRunner::run("sudo", &["ufw", "--force", "reset"])
}
pub fn default_deny_incoming(&self) -> Result<(), UfwError> {
CommandRunner::run("sudo", &["ufw", "default", "deny", "incoming"])
}
pub fn default_allow_outgoing(&self) -> Result<(), UfwError> {
CommandRunner::run("sudo", &["ufw", "default", "allow", "outgoing"])
}
pub fn raw_status(&self) -> Result<String, UfwError> {
CommandRunner::output("sudo", &["ufw", "status"])
}
pub fn port(&self, port: u16) -> PortBuilder<'_> {
PortBuilder::new(self, port)
}
pub fn ipv4(&self, ip: &str) -> Result<Ipv4Builder<'_>, UfwError> {
let addr: Ipv4Addr = ip
.parse()
.map_err(|_| UfwError::InvalidIpv4(ip.to_string()))?;
Ok(Ipv4Builder::new(self, IpAddr::V4(addr)))
}
pub fn ipv6(&self, ip: &str) -> Result<Ipv6Builder<'_>, UfwError> {
let addr: Ipv6Addr = ip
.parse()
.map_err(|_| UfwError::InvalidIpv6(ip.to_string()))?;
Ok(Ipv6Builder::new(self, IpAddr::V6(addr)))
}
pub fn ports(&self) -> Result<Vec<PortRule>, UfwError> {
let raw = CommandRunner::output("sudo", &["ufw", "status", "numbered"])?;
parse_port_rules(&raw)
}
pub fn ips(&self) -> Result<Vec<IpRule>, UfwError> {
let raw = CommandRunner::output("sudo", &["ufw", "status", "numbered"])?;
parse_ip_rules(&raw)
}
}