From 0bad1c7b665df6650b4a46add01463afabfaf8bc Mon Sep 17 00:00:00 2001 From: pyro Date: Thu, 17 Sep 2026 13:11:33 -0500 Subject: [PATCH] added the ability to exclude hosts and net ranges to projects so that excluded hosts are not touched by the tool. --- src/appstate.rs | 42 +++++++++++++++++++++++++++++++++++------- src/project.rs | 32 ++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/appstate.rs b/src/appstate.rs index f9850f8..99f002d 100644 --- a/src/appstate.rs +++ b/src/appstate.rs @@ -281,6 +281,7 @@ impl AppState { self.help.push( "Shortcuts:\nCTRL+P = new_project\nCTRL+s = save\nCTRL_+h = select_host\n".to_string(), ); + self.help.push("exclude\nexcludes an IP or a cidr network from the scope and all future tool calls.\nexport 192.168.1.1 192.168.2.0/24\n".to_string()); self.help.push("exit\nquit the tool\n".to_string()); self.initialize_modules(); return Ok(()); @@ -1151,15 +1152,17 @@ impl AppState { } 2 => { args_vec[0].split(",").into_iter().for_each(|ip| { - if let Ok(ip) = ip.parse::() { - let mut new_host = Host::new(); - new_host.ip = ip.to_string(); - hosts.push(new_host); - } else if let Ok(net) = ip.parse::() { - for host_addr in net.hosts() { + if !project.exclusions.contains(&ip.to_string()) { + if let Ok(ip) = ip.parse::() { let mut new_host = Host::new(); - new_host.ip = host_addr.to_string(); + new_host.ip = ip.to_string(); hosts.push(new_host); + } else if let Ok(net) = ip.parse::() { + for host_addr in net.hosts() { + let mut new_host = Host::new(); + new_host.ip = host_addr.to_string(); + hosts.push(new_host); + } } } }); @@ -1660,6 +1663,30 @@ impl AppState { } } + "exclude" => { + if let Some(args) = command_args { + let project = self.projects[self.selected_project].clone(); + if args.contains(" ") { + args.split(" ") + .into_iter() + .filter(|ex| !project.exclusions.contains(&ex.to_string())) + .for_each(|ex| { + if let Ok(_) = ex.parse::() { + self.projects[self.selected_project] + .exclusions + .push(ex.to_string()); + } else if let Ok(net) = ex.parse::() { + net.hosts().into_iter().for_each(|ip| { + self.projects[self.selected_project] + .exclusions + .push(ip.to_string()); + }); + } + }); + } + } + } + "exit" => { self.save_all()?; let _ = self.main_tx.send(ToolMessage::AppStateExit); @@ -1945,6 +1972,7 @@ impl AppState { current: false, db: db, scope: Vec::new(), + exclusions: Vec::new(), }; match new_project.save_config() { Ok(_) => {} diff --git a/src/project.rs b/src/project.rs index 7d19bd9..d193517 100644 --- a/src/project.rs +++ b/src/project.rs @@ -10,6 +10,7 @@ use std::net::IpAddr; use std::path::PathBuf; use std::process::{Command, Stdio}; use std::sync::mpsc::Sender; +use walkdir::WalkDir; #[derive(Clone, Debug)] pub struct Project { @@ -22,6 +23,7 @@ pub struct Project { pub current: bool, pub db: Option, pub scope: Vec, + pub exclusions: Vec, } impl Project { @@ -36,6 +38,7 @@ impl Project { current: false, db: None, scope: Vec::new(), + exclusions: Vec::new(), } } @@ -56,16 +59,18 @@ impl Project { } pub fn add_host(&mut self, mut host: Host) { - let mut new_id = 0; - self.hosts.iter().for_each(|h| { - if h.id > new_id { - new_id = h.id.clone(); + if !self.exclusions.contains(&host.ip) { + let mut new_id = 0; + self.hosts.iter().for_each(|h| { + if h.id > new_id { + new_id = h.id.clone(); + } + }); + new_id += 1; + if !self.hosts.iter().any(|h| h.ip == host.ip) { + host.id = new_id; + self.hosts.push(host); } - }); - new_id += 1; - if !self.hosts.iter().any(|h| h.ip == host.ip) { - host.id = new_id; - self.hosts.push(host); } } @@ -106,6 +111,12 @@ impl Project { self.add_scope(ip.trim().to_string()); }); } + "exclusions" => { + let ips: Vec<&str> = parts[1].split(",").collect(); + ips.iter().for_each(|ip| { + self.exclusions.push(ip.to_string()); + }); + } _ => {} } } @@ -225,12 +236,13 @@ impl Project { } let mut file = File::create(&self.config_folder)?; let mut out_string = format!( - "org_name: {}\nname: {}\nnotes: {}\nfiles: {}\nscope: {}\n", + "org_name: {}\nname: {}\nnotes: {}\nfiles: {}\nscope: {}\nexclusions: {}\n", self.org_name, self.name, self.notes.display(), self.files.display(), self.scope.join(","), + self.exclusions.join(","), ); if self.current { out_string.push_str("stage: current");