pub use crate::message::*; pub use crate::monitor::*; use serde::Deserialize; extern crate regex; // use regex::Regex; extern crate chrono; // use chrono::Local; #[derive(Debug)] pub struct NmapScanner { config: NmapScannerConfig, } #[derive(Debug, PartialEq, Deserialize)] struct NmapScannerConfig { #[serde(default)] args: Vec, #[serde(default)] ip_range: Option, #[serde(default)] period: Option, } impl Monitor for NmapScanner { fn new(config: serde_yaml::Value) -> Result> { let mut config: NmapScannerConfig = serde_yaml::from_value(config)?; if config.ip_range.is_none() { // Detect current subnet config.ip_range = Some("192.168.0.1-254".to_owned()); } // Regex compilation // let rgx_lease = Regex::new(r"(?s)lease\s+(\d+(?:\.\d+){3})\s*\{\n?(.*?)\}").unwrap(); // let rgx_mac = // Regex::new(r"(?m)^\s*hardware\s+ethernet\s([a-f0-9]{2}(?::[a-f0-9]{2}){5})\s*;") // .unwrap(); // let rgx_date_start = Regex::new(r"(?m)^\s*starts\s+\d+\s+(.*?)\s*;").unwrap(); // let rgx_date_ends = Regex::new(r"(?m)^\s*ends\s+\d+\s+(.*?)\s*;").unwrap(); Ok(NmapScanner { config: config }) } fn run(&mut self, sender: &mpsc::Sender) { // ex: nmap -sV -T4 -O -F --version-light 192.168.0.1-254 use std::process::{Command, Stdio}; let res = Command::new("nmap") .args(&self.config.args) .arg(&self.config.ip_range.clone().unwrap()) .args(vec!["-oX", "-"]) .stderr(Stdio::inherit()) .output() .expect("failed to execute process"); if res.status.success() { let output = std::str::from_utf8(&res.stdout).expect("UTF-8 decoding error"); // println!("{}", output); use serde_xml::value::{Content, Element}; let xml: Element = serde_xml::de::from_str(&output).expect("Bad XML format"); if let Content::Members(nodes) = xml.members { if let Some(hosts) = nodes.get("host") { for host_node in hosts { if let Content::Members(host) = &host_node.members { let address_nodes = host.get("address").unwrap(); let address = &address_nodes[0].attributes.get("addr").unwrap()[0]; let address_nodes = host.get("address").unwrap(); println!("address={:?}", address); } } } } // println!("{:?}", ); } std::thread::sleep(std::time::Duration::from_millis( (self.config.period.unwrap_or(60.0) * 1000.0) as u64, )); } } /* lease 192.168.0.26 { starts 4 2018/08/16 22:31:22; ends 4 2018/08/16 23:01:22; tstp 4 2018/08/16 23:01:22; cltt 4 2018/08/16 22:31:22; binding state free; hardware ethernet 84:4b:f5:16:f4:94; } */